티스토리 뷰

반응형

.NET 5.0은 최근에 출시되었으며 많은 새로운 기능과 성능 향상을 제공합니다. System.Text.Json도 예외는 아닙니다. 우리는 성능과 안정성을 향상 시켰으며 Newtonsoft.Json에 익숙한 사람들이 쉽게 채택 할 수 있도록했습니다. 이 게시물에서는 System.Text.Json으로 이루어진 진행 상황과 다음에 올 내용에 대해 이야기하겠습니다.

 

What's next for System.Text.Json? | .NET Blog (microsoft.com)

 

What's next for System.Text.Json? | .NET Blog

Learn about the new performance, reliaility and easy adoption that has been made with System.Text.Json, and what’s going to come next.

devblogs.microsoft.com

Getting the library

  • 프로젝트가 .NET 5를 대상으로하는 경우 .NET 5를 설치합니다. 이렇게하면 다른 전제 조건없이 바로 System.Text.Json이 제공됩니다.
  • 프로젝트가 .NET Core 3.x 또는 .NET Framework를 대상으로하거나 .NET Standard 호환 라이브러리를 작성하는 경우 최신 System.Text.Json NuGet 패키지를 설치합니다.
  • 새 ASP.NET Core 프로젝트를 시작하거나 기존 프로젝트를 ASP.NET Core 2.2에서 3.0 또는 5.0으로 업그레이드하는 경우 System.Text.Json이 내부적으로 사용되는 기본 직렬화 라이브러리입니다.

What is System.Text.Json?

System.Text.Json은 UTF-8 텍스트 인코딩을 지원하는 .NET 개체 형식에서 JSON 문자열로 또는 그 반대로 변환하기위한 .NET의 기본 제공 JSON (JavaScript Object Notation) 직렬화 라이브러리입니다. .NET Core 3.0에서 처음 추가되었습니다. 라이브러리에서 널리 사용되는 유형은 JSON 데이터 처리를위한 최고 수준의 기능을 제공하는 JsonSerializer입니다. 다음은 이를 사용하여 .NET 객체 유형과 JSON을 직렬화 및 역직렬화하는 방법에 대한 간단한 예입니다.

using System;
using System.Text.Json;

MyType obj = new() { Message = "Hello World!" };

string json = JsonSerializer.Serialize(obj);
Console.WriteLine(json); // {"Message":"Hello World!"}

MyType anotherObject = JsonSerializer.Deserialize<MyType>("{"Message":"Hello Again."}");
Console.WriteLine(anotherObject.Message); // "Hello Again."

public class MyType
{
    public string Message { get; set; }
}

Why System.Text.Json? Looking back at .NET Core 3.x

JSON 데이터 처리는 많은 최신 .NET 응용 프로그램에서 필수적인 부분이되었으며 대부분의 경우 형식이 XML 사용을 능가했습니다. 그러나 .NET에는 JSON을 처리하는 훌륭한 기본 제공 방법이 없었습니다. 대신 사용자는 계속해서 .NET 생태계를 잘 지원하는 Newtonsoft.Json에 의존했습니다. 이 것으로 고객이 프레임워크의 일부로 제공되는 최신 JSON 라이브러리를 통해 이점을 얻을 수 있다는 것이 분명해졌습니다. 따라서 다음 사항을 고려하여 새 JSON 라이브러리를 구축했습니다.

  • 고성능 JSON API를 제공합니다. 성능을 위해 고도로 조정되고 Span<T>와 같은 프레임워크에 대한 최신 추가 기능을 활용하며 UTF-16 문자열로 트랜스 코딩하지 않고도 UTF-8을 직접 처리 할 수있는 새로운 JSON API 세트가 필요했습니다. 이러한 측면은 처리량이 핵심 요구 사항 인 ASP.NET Core에 중요합니다. 우리는 Newtonsoft.Json에 대한 변경 사항에 기여하는 것을 고려했지만 기존 Newtonsoft.Json 사용자를 해치거나 우리가 달성 할 수있는 성능을 손상시키지 않고는 실현 불가능한 것으로 간주되었습니다.
  • ASP.NET Core에서 Newtonsoft.Json 종속성을 제거합니다. .NET Core 3.x 이전에는 ASP.NET Core가 Newtonsoft.Json에 종속되었습니다. 이것은 ASP.NET Core와 Newtonsoft.Json 간의 긴밀한 통합을 제공했지만 Newtonsoft.Json의 버전이 기본 플랫폼에 의해 결정되었음을 의미하기도 했습니다. 그러나 Newtonsoft.Json은 자주 업데이트되고 응용 프로그램 개발자는 종종 특정 버전을 사용해야했습니다. 따라서 우리는 ASP.NET Core 3.0에서 Newtonsoft.Json 종속성을 제거하여 고객이 실수로 기본 플랫폼을 손상시킬 수 있다는 두려움없이 사용할 버전을 선택할 수 있도록했습니다.

.NET 생태계에서 Newtonsoft.Json의 편재성을 감안할 때, 우리는 직렬화 메커니즘으로 다시 추가 할 수 있는 쉬운 방법을 제공하지 않고 ASP.NET Core에서 종속성을 제거하고 싶지 않았습니다. 이를 수행하는 방법은 다음과 같습니다.

services.AddMvc()
    .AddNewtonsoftJson();

자세한 내용은 Newtonsoft.Json (Json.NET) 지원을 참조하세요.

What we shipped in .NET Core 3.0

.NET Core 3.0에서는 System.Text.Json 네임 스페이스에 다음 형식을 제공했습니다.

  • JsonSerializer : .NET 개체를 JSON 표현으로 직렬화하고 JSON을 .NET 개체로 역직렬화하는 기능을 제공합니다.
  • JsonDocument : 데이터 값을 자동으로 인스턴스화하지 않고 JSON 값의 구조적 콘텐츠를 검사하기위한 임의 액세스 기능을 제공합니다. 이 유형은 변경할 수 없습니다.
  • JsonElement : JsonDocument 내의 특정 JSON 값을 나타냅니다.
  • Utf8JsonWriter : UTF-8로 인코딩 된 JSON 텍스트의 포워드 전용, 캐시되지 않은 쓰기를 위한 고성능 API를 제공합니다.
  • Utf8JsonReader : UTF-8로 인코딩 된 JSON 텍스트의 정방향 전용, 토큰 별 처리를위한 고성능 API를 제공합니다.

System.Text.Json.Serialization 네임 스페이스에서 JsonSerializer를 사용한 직렬화 및 역직렬화와 관련된 고급 시나리오 및 사용자 지정을위한 특성 및 API를 제공했습니다. 이 중에서 인기있는 것은 사용자가 특정 유형, 속성 또는 필드의 직렬화 및 역직렬화를 제어 할 수있는 JsonConverter<T> 유형입니다.

 

JsonSerializer는 JSON 데이터 처리를 위한 최고 수준의 기능을 제공합니다. 지속적인 데이터 형식과 .NET 개체 유형간에 변환하기 위해 직렬 변환기를 구현하는 광범위한 기능으로 인해 JsonSerializer는 JSON 스택의 다른 유형보다 훨씬 더 많은 개발을 진행하고 더 많은 커뮤니티 피드백을 받고 있습니다. 따라서이 게시물에서는 주로 JsonSerializer 기능을 다룰 것입니다.

 

3.0에서는 JsonSerializer에 다음 기능이 포함되었습니다.

  • POCO(Plain Old CLR Object), 기본 및 컬렉션 직렬화 및 역직렬화 지원
  • 기본 제공 비동기 직렬화 및 역직렬화
  • UTF-8 데이터의 기본 처리
  • 대소 문자를 구분하지 않는 역직렬화 (대소 문자 구분 외에)
  • JsonNamingPolicy.CamelCase를 사용한 Camel-case 명명 정책
  • JsonNamingPolicy로 사용자 지정 명명 정책 지정
  • 이스케이프 된 JSON 데이터 역직렬화
  • 직렬화시 선택적 최소 문자 이스케이프
  • 직렬화에서 null 값 무시
  • 역직렬화에 대한 주석 무시
  • 후행 쉼표 허용
  • 맞춤형 변환기
  • [JsonExtensionData] 속성을 사용하여 역직렬화 할 때 속성 오버플로 백 표시
  • [JsonIgnore] 속성을 사용하여 개별 속성 무시
  • [JsonProperty] 속성을 사용하여 사용자 정의 속성 이름 지정

System.Text.Json이 제공하는 기능에 대한 개요는 .NET의 JSON 직렬화 및 역 직렬화 (마샬링 및 비 마샬링)를 참조하세요.

Choosing between System.Text.Json and Newtonsoft.Json

Feature differences

이제 System.Text.Json을 사용하려면 Newtonsoft.Json에서 마이그레이션해야합니까? 그 질문에 대한 대답은 상황에 따라 다르다는 것입니다. .NET Core 3.0에서는 System.Text.Json이 대부분의 애플리케이션에 충분하다고 믿기 때문에 ASP.NET Core의 기본 serializer로 만들었습니다. 그러나 예를 들어 Newtonsoft.Json의 여러 속성을 사용하여 직렬화 동작을 크게 사용자 정의한 경우 주로 POCO를 사용하는 사람과 달리 마이그레이션하기가 더 어려울 수 있습니다. 자세한 내용은 Newtonsoft.Json에서 System.Text.Json으로 마이그레이션하는 방법에 대한 설명서를 확인하십시오.

 

System.Text.Json은 새로운 .NET 애플리케이션을 위한 기본 JSON 처리 스택이므로 주로 성능, 보안 및 표준 준수에 중점을 둡니다. 기본 동작에 몇 가지 주요 차이점이 있으며 Newtonsoft.Json과 기능 패리티를 갖는 것을 목표로하지 않습니다. 일부 시나리오의 경우 System.Text.Json에는 기본 제공 기능이 없지만 권장되는 해결 방법이 있습니다. 다른 시나리오의 경우 해결 방법이 비현실적입니다. 애플리케이션이 누락 된 기능에 의존하는 경우 문제를 제출하여 시나리오에 대한 지원을 추가 할 수 있는지 알아보십시오.

 

System.Text.Json에 기능이나 유연성이 없거나 Newtonsoft.Json이 느리다는 것은 아닙니다. 이는 다양한 디자인 철학과 기능이 성능이나 유연성과 충돌 할 때 긴장을 해결하는 방법을 설명하기 위한 것입니다. System.Text.Json의 목표는 성능, 보안 및 기능 세트의 균형을 유지하는 빠른 내장 JSON 스택을 제공하는 것입니다. 모든 기능 요청은 이러한 설계 원칙에 따라 신중하게 평가됩니다. 이는 이러한 원칙에 부합하는 새 프로젝트가 System.Text.Json을 더 쉽게 사용할 수있는 반면, 이전 프로젝트는 마이그레이션 중에 더 많은 장애물에 직면 할 수 있음을 의미 할 수 있습니다. 그러나 Newtonsoft.Json에는 아무런 문제가 없습니다. 만족 스러우면 계속 사용해야합니다.

 

가까운 장래에 System.Text.Json에 추가 할 계획이없는 기능의 두 가지 예를 제공하겠습니다.

  • System.ComponentModel.TypeConverter를 통한 형식 변환
  • System.Runtime.Serialization 특성을 통한 직렬화 동작 조정

이 두 가지 모두 이전 직렬화 스택의 레거시 시스템으로 간주되며,이를 지원하는 것은 시작시 추가 반사 기반 조회로 인해 System.Text.Json의 성능 우선 아키텍처에 위배되며 더 많은 유지 관리 및 크기 부담을 가져옵니다. System.Text.Json.dll의 코드. 또한 deserialization에서 잘못된 형식의 JSON 처리를 허용하는 것과 같이 표준 준수 원칙에 위배되는 모든 기능은 허용되지 않습니다.

 

확장 성을 염두에두고 System.Text.Json을 설계하고 있습니다. 즉, 위의 기능이 JsonSerializer 내에서 기본 지원이 없더라도 사용자가 제공 한 구성에서 계속 지원할 수 있습니다. 예를 들어 사용자는 사용자 지정 JsonConverter<T>를 사용하여 TypeConverters 호출에 대한 래퍼를 작성할 수 있습니다. 또한 IContractResolverJsonProperty와 유사한 메커니즘 (Newtonsoft.Json에서 제공)을 고려하여 System.Runtime.Serialization을 준수하기위한 사용자 지정 지원을 허용하는 형식 및 멤버 (dotnet/runtime #31257)에 대한 메타 데이터 및 직렬화 논리 설정을 프로그래밍 방식으로 제어 할 수 있습니다.

 

JsonSerializer는 기본 제공 성능 기능으로 JSON 데이터의 비동기 직렬화 및 역직렬화를 지원합니다. 이는 비동기 JSON 처리를 지원하는 기본 제공 메커니즘이없는 Newtonsoft.Json을 통해 응답성과 non-blocking이 필요한 확장성이 뛰어난 애플리케이션을 작성하는 고객에게 상당한 가치를 제공하는 것으로 나타났습니다.

 

UTF-8 인코딩은 유선을 통한 정보 전송을 위한 사실상의 기본형식입니다. System.Text.Json API는 기본적으로 이 인코딩을 사용하여 데이터를 처리하며 Newtonsoft.Json과 달리 UTF-16간에 트랜스 코딩 할 필요가 없습니다. 또한 호출자는 데이터를 System.Text.Json API에 입력으로 전달하기 전에 데이터를 수동으로 트랜스 코딩 할 필요가 없습니다. 이 트랜스 코딩을 피하면 JSON 데이터를 처리 할 때 더 나은 성능을 얻을 수 있습니다. string-based (UTF-16) API도 편의상 사용할 수 있지만 트랜스 코딩 비용이 발생합니다.

Performance

.NET Core 3.0 개발주기 동안 System.Text.Json 성능이 Newtonsoft.Json과 어떻게 비교되는지에 대해 블로그를 작성했습니다.

Scenario Speed Memory
Deserialization 2x faster Parity or lower
Serialization 1.5x faster Parity or lower
Document (read-only) 3-5x faster ~Allocation free for sizes < 1 MB
Reader 2-3x faster ~Allocation free (until you materialize values)
Writer 1.3-1.6x faster ~Allocation free

모든 성능 벤치 마크와 마찬가지로 시나리오가 다양하며 요약 수치는 미묘합니다. 그 게시물의 요약은 다음과 같습니다.

주요 목표는 성능이었고 Json.NET에 비해 일반적인 속도가 최대 2 배 향상되었지만 시나리오와 페이로드에 따라 다르므로 중요한 사항을 측정해야합니다.

어떤 사람들은이를 System.Text.Json이 항상 두 배나 빠르다는 의미로 생각했습니다. "최대"및 "시나리오 및 페이로드에 따라 다름"문장이 그 문장의 핵심입니다.

 

.NET 에코 시스템에서 JsonSerializer와 다른 serializer간에 여러 성능 비교가 있었습니다. JsonSerializer가 항상 가장 빠른 것은 아닙니다. 왜 그것이 성능이 주요 목표라고 말했는지 궁금 할 것입니다. 소프트웨어에서는 다른 기능을 손상시키지 않고 거의 모든 기능을 최대화 할 수 없으므로 모든 기능은 다양한 측면 간의 균형입니다. JSON 직렬화의 성능은 우리에게 매우 중요하지만 이것이 우리가 가진 유일한 목표는 아닙니다. 다른 목표에는 보안, 안정성, 표준 준수 및 유용성이 포함됩니다.

 

다음은 더 나은 성능에 대한 몇 가지 장단점의 몇 가지 예입니다.

  • Using classes in some cases. 우리는 Utf8JsonWriter를 클래스로 만들기로 결정했습니다. 이전에는 더 적은 할당과 우리가 쓰는 기본 범위에 대한 더 빠른 액세스를 허용하는 ref struct였습니다. 개발자가 실수로 작성자의 복사본을 만들고 (예 : 값으로 도우미 메서드에 전달할 때) 후속 쓰기가 버퍼의 데이터를 덮어 쓰는 문제를 방지하기 위해 class로 변경했습니다.
  • Validation. 처리중인 JSON 데이터의 유효성을 검사하기로 결정했습니다. 여기에는 UTF-8 유효성 검사와 JSON 구문 유효성 검사가 모두 포함됩니다. 이는 JSON 입력이 종종 신뢰할 수 없는 소스에서 나오는 서버 및 클라우드 시나리오를 활성화하는 데 필요합니다.
  • Extension points. 직렬 변환기에는 사용자 지정 변환기를 등록하는 기능이 있습니다. 이러한 간접적인 방법은 상대적으로 저렴하지만 타이트한 루프에서 실행할 때 비용이 많이 듭니다. 때로는 사용되지 않는 경우에도 마찬가지입니다 (조회 때문에).

What’s new in .NET 5.0?

New features

.NET 5.0에서는 커뮤니티에서 가장 많이 찾는 기능 중 일부를 구현했으며 Newtonsoft.Json에 익숙한 사람들이 쉽게 채택 할 수 있도록했습니다. 다음은 추가 된 기능에 대한 개요입니다.

GitHub Issue Description
#30820 (역)직렬화 할 때 객체 참조를 보존하는 메커니즘 추가
#32937 JSON (역)직렬화를 허용하는 HttpClient 및 HttpContent에 대한 확장 메서드 추가
#30255 인용된 숫자 (역)직렬화 지원
#29895 매개 변수가 있는 생성자를 사용하여 개체 (역)직렬화 지원
#876 필드 (역)직렬화 지원
#779 값 유형 기본값 무시 지원
#30687 조건부 무시 속성 지원 (null/default 일 때 항상, 절대 안 함)
#30524 문자열이 아닌 사전 키 지원
#29743 (역)직렬화에 비공개 속성 접근자를 사용하도록 허용
#34439 null을 처리 할 사용자 지정 변환기에 대한 옵트인 제공
#38539 새로운 C# record type 지원
#30445 JsonSerializerOptions에 복사 생성자 추가
#34626 직렬화 기본값을 사용하는 JsonSerializerOptions에 생성자 추가
#31326 Xamarin iOS/Android에서 작동하도록 JsonSerializer 사용

.NET 5.0 및 .NET 5.0 RC 1을 발표했을 때 변경 불가능한 유형에 대한 개선된 지원과 JSON 개체 그래프의 참조 보존을 포함한 몇 가지 새로운 기능에 대해 살펴 보았습니다. 이 섹션에서는 몇 가지 더 살펴 보겠습니다.

Support for quoted numbers

.NET Core 3.0이 출시되었을 때 JSON 문자열로 인코딩 된 숫자 형식 역직렬화는 기본적으로 지원되지 않습니다. 해결 방법은 해당 유형의 직렬화 및 역 직렬화를 제어하고 인용 된 숫자를 처리하는 논리를 포함하는 각 해당 숫자 유형에 대한 사용자 지정 변환기를 추가하는 것이 었습니다. .NET 5에서는 인용 된 숫자의 직렬화 및 역직렬화와 명명 된 부동 소수점 리터럴 (NaN, Infinity-Infinity)을 지원하는 편리한 옵트 인 기능을 추가했습니다. 다음은이 기능을 사용하는 예입니다.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

var options = new JsonSerializerOptions
{
    NumberHandling = JsonNumberHandling.AllowReadingFromString | 
        JsonNumberHandling.WriteAsString
};

string json = @"{""NumberOne"":1,""NumberTwo"":""2""}";

ClassWithInts @class = JsonSerializer.Deserialize<ClassWithInts>(json, options);
Console.WriteLine(@class.NumberOne); // 1
Console.WriteLine(@class.NumberTwo); // 2

json = JsonSerializer.Serialize(@class, options);
Console.WriteLine(json); // @"{""NumberOne"":""1"",""NumberTwo"":""2""}";

public class ClassWithInts
{
    public int NumberOne { get; set; }
    public int NumberTwo { get; set; }
}

전역적으로 적용되는 JsonSerializerOptions.NumberHandling 옵션 외에도 유형, 속성 또는 필드에 대한 숫자 처리 설정을 지정할 수있는 JsonNumberHandlingAttribute도 추가되었습니다.

Extended support for ignoring default values

.NET Core 3.x에서 직렬화 할 때 참조 또는 nullable 값 형식 속성에 대한 null 값만 무시할 수 있었고 JsonSerializerOptions.IgnoreNullValues ​​설정은 전체 입력 개체 그래프에만 적용 할 수있었습니다. .NET 5에서는 intfloat와 같은 nullable이 아닌 값 유형에 대한 default을 무시하는 지원을 추가했습니다. 또한 기본적으로 무시할 속성과 필드를 체리로 선택할 수 있습니다. 다음 예를 참조하십시오.

var options = new JsonSerializerOptions
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
};

var obj = new MyClass();
string json = JsonSerializer.Serialize(obj, options);
Console.WriteLine(json); // {"MyBool":false}

public class MyClass
{
    public int MyInt { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
    public bool MyBool { get; set; }

    public string MyString { get; set; }
}

여기에서 새로운 기능의 조합을 볼 수 있습니다. serializer가 전체 개체 그래프에서 default값을 무시하도록 지시하지만 전역 옵션에 관계없이 속성 중 하나를 무시해서는 안됨을 나타냅니다. null 값만 무시하고 값 형식의 기본값은 무시하려면 JsonIgnoreCondition.WhenWritingNull을 사용합니다.

 

default값 처리에 대한 이러한 증가를 통해 JsonSerializerOptions.IgnoreNullValues ​​속성은 다가오는 .NET 6.0 릴리스에서 더 이상 사용되지 않습니다. IgnoreNullValues는 직렬화 할 때뿐만 아니라 역직렬화 할 때도 적용됩니다. 입력 페이로드에서 null 토큰을 무시할 이유가 없기 때문에 바람직하지 않습니다.

Utility constructors for JsonSerializerOptions

한 인스턴스에서 다른 인스턴스로 JsonSerializerOptions 설정을 복사 한 다음 몇 가지 변형을 만드는 것은 일반적인 작업입니다. .NET 5에서는 JsonSerializerOptions에 복사 생성자를 추가하여 이를 더 쉽게 만듭니다.

JsonSerializerOptions options = new()
{
    NumberHandling = JsonNumberHandling.AllowReadingFromString,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    Converters = { new JsonStringEnumConverter() }
};

JsonSerializerOptions newOptions = new(options)
{
    NumberHandling = JsonNumberHandling.Strict
};

Console.WriteLine(newOptions.NumberHandling);
// Strict
Console.WriteLine(newOptions.DefaultIgnoreCondition);
// WhenWritingNull
Console.WriteLine(newOptions.Converters[0]);
// System.Text.Json.Serialization.JsonStringEnumConverter

웹 컨텍스트에서 JSON 데이터를 처리 할 때 일반적인 옵션 세트는 camelCase 이름 지정 정책을 사용하고 역직렬화 할 때 대소 문자를 구분하지 않는 일치를 지정하고 인용된 숫자를 읽을 수 있도록 허용하는 것입니다. 새로운 JsonSerializerDefaults.Web 열거 형 값은 JsonSerializerDefaults 값을 사용하는 새 생성자와 함께 애플리케이션의 여러 계층 (예 : Blazor 시나리오의 경우 클라이언트, 공유 및 서버)에서 일관된 방식으로 이러한 옵션을 재사용 할 수 있는 쉬운 방법을 제공합니다.

JsonSerializerOptions options = new(JsonSerializerDefaults.Web);
Console.WriteLine(options.PropertyNamingPolicy);
// System.Text.Json.JsonCamelCaseNamingPolicy
Console.WriteLine(options.PropertyNameCaseInsensitive);
// True
Console.WriteLine(options.NumberHandling);
// AllowReadingFromString

Newtonsoft.Json과 비교하여 JsonSerializer가 지원하는 기능에 대한 자세한 내용은 마이그레이션 가이드에서이 표를 확인하세요.

Performance improvements

.NET Core 3.1과 .NET 5 사이에서 다음 영역에서 성능이 향상되었습니다.

  • 컬렉션의 직렬화 및 역 직렬화 성능 향상
  • 소형 유형에 대한 직렬화 및 역 직렬화 성능 향상
  • 대소 문자를 구분하지 않고 속성이 누락 된 경우에 대한 역 직렬화 성능 향상
  • 긴 JSON 문자열에 대한 직렬화 성능 향상

이러한 개선 사항은 고성능 앱에 특히 의미가있을 것입니다.

Improved performance for collections

대규모 컬렉션 (역직렬화시 ~ 1.15x-1.5x, 직렬화시 ~ 1.5x-2.4x)을 크게 개선했습니다. 이러한 개선 사항은 dotnet/runtime #2259에서 훨씬 더 자세히 확인할 수 있습니다. 다음 숫자는 1,024 개의 요소가있는 컬렉션을 처리하기위한 성능 수치를 보여줍니다.

Dictionary<string, string>

Method Mean Error StdDev Median Min Max Gen 0 Gen 1 Gen 2 Allocated
Deserialize Before 190.4 us 1.47 us 1.38 us 190.6 us 188.5 us 193.6 us 26.5554 8.3460 163.69 KB
After ~1.2x faster 158.8 us 1.27 us 1.13 us 158.8 us 157.3 us 161.3 us 26.5991 8.8664 164.05 KB
Serialize Before 109.7 us 0.77 us 0.72 us 109.5 us 108.5 us 111.1 us 3.4904 23.92 KB
After ~1.5x faster 74.53 us 0.590 us 0.552 us 74.40 us 73.57 us 75.69 us 3.8179 0.2937 24.17 KB

List<int>

Method Mean Error StdDev Median Min Max Gen 0 Gen 1 Gen 2 Allocated
Deserialize Before 76.40 us 0.392 us 0.366 us 76.37 us 75.53 us 76.87 us 1.2169 8.25 KB
After ~1.5x faster 50.05 us 0.251 us 0.235 us 49.94 us 49.76 us 50.43 us 1.3922 8.62 KB
Serialize Before 29.04 us 0.213 us 0.189 us 29.00 us 28.70 us 29.34 us 1.2620 8.07 KB
After ~2.4x faster 12.17 us 0.205 us 0.191 us 12.15 us 11.97 us 12.55 us 1.3187 8.34 KB

Improved performance for small types (TechEmpower benchmarks)

.NET 5.0에서는 TechEmpower JSON 벤치 마크에서 .NET 성능을 개선하기 위한 상당한 노력이 있었습니다. 이 작업은 네트워킹 스택, Kestrel 및 JsonSerializer 자체를 포함하여 여러 영역에 걸쳐있었습니다. 결과적으로 직렬화 기내에서 수행 된 작업을 관찰 할 때 성능이 이제 ~19% 향상되었습니다.

 

이러한 변경 사항과 성능 측정은 dotnet/runtime #37976에서 자세히 다룹니다. 거기에는 두 세트의 벤치 마크가 있습니다. 첫 번째는 팀이 유지 관리하는 JsonSerializer 성능 벤치 마크로 성능을 검증하는 것입니다. ~8% 개선이 관찰되었습니다. 다음 섹션은 TechEmpower입니다. TechEmpower JSON 벤치 마크의 요구 사항을 충족하기 위해 세 가지 접근 방식을 측정합니다. SerializeWithCachedBufferAndWriter는 공식 벤치 마크에서 사용하는 것입니다.

Method Mean Error StdDev Median Min Max Gen 0 Gen 1 Gen 2 Allocated
SerializeWithCachedBufferAndWriter (Before) 155.3 ns 1.19 ns 1.11 ns 155.5 ns 153.3 ns 157.3 ns 0.0038 24 B
SerializeWithCachedBufferAndWriter (After) ~1.19x faster 130.8 ns 1.50 ns 1.40 ns 130.9 ns 128.6 ns 133.0 ns 0.0037 24 B

스택 전체에서 수행된 모든 작업은 항목을 .NET 5.0으로 업데이트하면 JSON TechEmpower 벤치 마크에서 .NET의 배치를 개선 할 것입니다. .NET 3.1 (2020-05-28 라운드 19) 벤치 마크의 aspcore 항목 성능을 .NET 5.0 (비공식 연속 실행, 2020-12-14)과 비교할 수 있습니다.

Before

After

JSON 직렬화에 대한 RPS (초당 응답)가 904,846에서 1,190,245로 증가하여 ~31% 향상되었음을 알 수 있습니다.

Improved deserialization performance for case-insensitive and extra-property cases

JSON 사용과 관련된 가장 일반적인 문제 중 하나는 .NET 디자인 지침과 명명 규칙이 일치하지 않는다는 것입니다. JSON 속성은 종종 camelCase이고 .NET 속성이며 필드는 일반적으로 PascalCase입니다. 사용하는 JSON 직렬 변환기는 명명 규칙 간의 브리징을 담당합니다. 적어도 .NET Core 3.1에서는 무료로 제공되지 않습니다. 이 비용은 이제 .NET 5.0에서 무시할 수 있습니다.

 

대소 문자를 구분하지 않고 추가 속성을 허용하는 코드가 .NET 5.0에서 크게 향상되었습니다. 어떤 경우에는 ~1.75 배 더 빠릅니다.

 

다음 벤치 마크는 속성 이름이 7 자 이상인 간단한 4 개 속성 테스트 클래스에 대한 것입니다.

3.1 performance

Method Mean Error StdDev Median Min Max Gen 0 Gen 1 Gen 2 Allocated
CaseSensitive_Matching 844.2 ns 4.25 ns 3.55 ns 844.2 ns 838.6 ns 850.6 ns 0.0342 224 B
CaseInsensitive_Matching 833.3 ns 3.84 ns 3.40 ns 832.6 ns 829.4 ns 841.1 ns 0.0504 328 B
CaseSensitive_NotMatching (Extra) 1,007.7 ns 9.40 ns 8.79 ns 1,005.1 ns 997.3 ns 1,023.3 ns 0.0722 464 B
CaseInsensitive_NotMatching 1,405.6 ns 8.35 ns 7.40 ns 1,405.1 ns 1,397.1 ns 1,423.6 ns 0.0626 408 B

5.0 performance

Method Mean Error StdDev Median Min Max Gen 0 Gen 1 Gen 2 Allocated
CaseSensitive_Matching 799.2 ns 4.59 ns 4.29 ns 801.0 ns 790.5 ns 803.9 ns 0.0985 632 B
CaseInsensitive_Matching 789.2 ns 6.62 ns 5.53 ns 790.3 ns 776.0 ns 794.4 ns 0.1004 632 B
CaseSensitive_NotMatching (Extra) 479.9 ns 0.75 ns 0.59 ns 479.8 ns 479.1 ns 481.0 ns 0.0059 40 B
CaseInsensitive_NotMatching 783.5 ns 3.26 ns 2.89 ns 783.5 ns 779.0 ns 789.2 ns 0.1004 632 B

Improve serialization performance for long JSON strings

dotnet/corefx #41845는 SSE2 내장 함수를 활용하여 보안 검사에서 JSON 문자열이 이스케이프되어야 하는지 더 빠르게 확인했습니다. 일반적으로 발견되는 페이로드를 직렬화하면 ~10-20% 개선됩니다. 또한 라이터를 직접 사용하여 비교적 큰 JSON 문자열을 작성할 때 ~30% 향상됩니다. 이 변경 사항의 성능 특성은이 GitHub 요점에서 자세히 설명합니다. 한 가지 흥미로운 데이터 포인트는 NuGet 검색 결과를 나타내는 POCO의 인스턴스를 직렬화 할 때 개선 사항을 보여주는 벤치 마크입니다.

Before:

Method Mean Error StdDev Median Min Max Gen 0 Gen 1 Gen 2 Allocated
SerializeNugetPayload (Before) 791.7 ms 15.69 ms 16.12 ms 787.4 ms 772.0 ms 827.1 ms 787.3 MB
SerializeNugetPayload (After) ~1.13x faster 698.4 ms 6.63 ms 5.53 ms 699.5 ms 690.9 ms 708.4 ms 787.3 MB

Breaking changes

.NET Core 3.x와 .NET 5.0간에 몇 가지 주요 동작을 변경했습니다. System.Text.Json이 플랫폼 구성 요소이고 나머지 .NET과 같은 엄격한 호환성 표준을 준수한다는 점을 감안할 때 이러한 변경 사항은 영향에 대한 신중한 평가를 기반으로 이루어졌으며 라이브러리 전체를 개선하는데 도움이됩니다. 중요하기는 하지만 이러한 변경 사항은 일반적으로 특히 일관성과 관련된 엣지 사례를 다루며 라이브러리를 사용하는 대다수의 사람들에게 최소한의 영향을 미칩니다. 보다 중요한 동작 변경 및 새로운 기능 추가를 위해 이전 버전의 라이브러리에 대해 작성된 기존 코드가 손상되지 않도록 옵트 인합니다. 각 주요 변경 사항에 대한 자세한 내용은 링크 된 문서를 참조하십시오.

What’s next for System.Text.Json?

.NET 6.0에 대한 계획을 시작했습니다. System.Text.Json을 더 많은 .NET 애플리케이션에서 JSON 스택에 대한 실행 가능한 선택으로 만드는 데 도움이되는 가장 많이 요청 된 기능을 계속해서 다루면서 각 요청을 설계 원칙과 비교해 볼 것입니다. 제안 된 내용에 대한 개요는 dotnet/runtime 43620을 참조하십시오. 다음은 몇 가지 주요 기능에 대한 간략한 설명입니다.

C# source generator for JSON serialization (dotnet/runtime #1568)

투자의 한 영역은 새로운 C# 소스 생성기 기능을 활용하여 다음 영역에서 serializer를 지원할 수있는 코드를 생성하는 것입니다.

  • 향상된 시작 성능
  • 향상된 런타임 처리량
  • 개인용 바이트 사용량 감소
  • 런타임 반영을 피하여 ILLinker 친 화성
  • 시리얼 라이저 및 사용하지 않는 변환기의 사용되지 않는 리플렉션 기반 코드 경로의 링커 제거를 용이하게하여 애플리케이션 크기 감소

이 노력은 진행 중이며 프로토 타입 단계에 있습니다. 작업 항목과 이러한 노력의 진행 상황은 dotnet/runtimelabJSON Code Gen 프로젝트 게시판을 통해 확인할 수 있습니다.

 

소스 생성을 지원하는 업데이트 된 System.Text.Json은 실험용 NuGet 패키지를 통해 사용할 수 있습니다. 이 기능을 사용할 때 관찰 한 성능 변화를 공유하십시오. area-JsonCodeGen 레이블을 사용하여 여기에 문제를 기록 할 수 있습니다.

Extended polymorphic serialization and deserialization (dotnet/runtime #45189)

다형성 직렬화 및 역직렬화는 현대 .NET 애플리케이션의 중요한 시나리오로 남아 있습니다. 이러한 시나리오를 가능하게하기 위해 .NET 6.0에서 기능 작업이 수행 될 것으로 예상됩니다.

dynamic and a mutable JSON DOM (dotnet/runtime #45188)

dynamic 유형 직렬화 및 역직렬화를 활성화하고 변경 가능한 JSON 문서를 제공하는 것은 많은 고객의 차단을 해제하는 밀접하게 관련된 두 가지 중요한 기능입니다. 우리는 이것들을 잠재적인 .NET 6.0. 작업으로 추적하고 있습니다.

Miscellaneous improvements (dotnet/runtime #45190)

.NET 6.0에서 만들고 싶은 여러 가지 기타 기능과 개선 사항이 있습니다. IAsyncEnumerable<T> 인스턴스 (dotnet/runtime #1570)의 비동기 직렬화 및 역직렬화를 지원하는 기능과 같은 일부 기능은 System.Text.Json에 혁신적이고 고유합니다. snake_case 지원 추가 (dotnet/runtime #782) 및 기본 JsonSerializerOptions 설정 (dotnet/runtime #31094) 변경과 같은 다른 기능은 더 익숙 할 것입니다. 이러한 기능을 구현하면 System.Text.Json이 적합한 앱의 수가 늘어납니다.

Closing

.NET 5.0은 System.Text.Json의 큰 릴리스였습니다. 프로젝트가 .NET 5.0을 대상으로하지 않는 경우에도 최신 System.Text.Json NuGet 패키지를 설치하여 새로운 개선 사항을 활용할 수 있습니다.

 

.NET 5.0에서 수행 한 많은 작업은 커뮤니티에서 주도했습니다. @YohDeadfall은 필드 지원을 구현하고 JsonSerializer에 다양한 최적화에 기여했습니다. @NikiforovAll은 JsonSerializerDefaults 값을 취하는 JsonSerializerOptions 생성자를 구현했습니다. @marcusturewicz는 JsonDocument 인스턴스의 직렬화 및 역 직렬화 지원을 구현했습니다. @devsko는 우리가 출시하기 전에 새로운 .NET 5.0 개선 사항과 함께 다양한 문제를 수정했습니다. @CodeBlanch는 null 및 null 허용 여부 문제에 대한 수정 사항을 제공했습니다. @Marusyk는 새로운 참조 보존 기능에 대한 참조 동등성을 가진 버그 수정에 기여했습니다. @khellang은 읽을 때 DateTime 및 DateTimeOffset 페이로드의 유효성 검사와 관련된 버그 수정에 기여했습니다. @alanisaac, @thomaslevesque, @marcusturewicz, @madmir, @NikiforovAll, @JoshSchreuder, @ Jacksondr5 및 @KimKiHyuk은 System.Text.Json을 100 %에 가깝게 만들기 위해 지속적으로 노력하면서 System.Text.Json의 테스트 범위를 개선하기위한 변경 사항에 기여했습니다. 여기에서 모든 기여를 강조 할 수는 없지만 .NET 감사 페이지는 .NET 런타임의 모든 기여자에게 찬사를 보냅니다.

 

.NET 6.0에서는 계속해서 더 많은 기능을 개선하고 있습니다. System.Text.Json에 대한 기여는 우리가 발전하는 동안 매우 환영합니다. 이 GitHub 쿼리를 방문하여 area-System.Text.Jsonup-for-grabs로 레이블이 지정된 문제를 찾으십시오. 대담하다고 느끼면 up-for-grabs 레이블이없는 문제를 확인하십시오. 언제나 그렇듯이, 특히 현재 다음 릴리스를 계획하고 있으므로 피드백을 환영합니다.

반응형

'.NET 5, 6, 7' 카테고리의 다른 글

MAUI in .NET 6: Xamarin.Forms Does Desktop, but Not Linux or VS Code  (0) 2021.01.26
Action<T>? Func<TResult>?  (2) 2021.01.21
.NET Conf 2021 x Seoul  (0) 2021.01.17
Xamarin.Forms 5.0 릴리즈!  (0) 2021.01.14
WinUI 3 Preview 3  (2) 2021.01.08
댓글