.NET用JSONシリアライザーのパフォーマンス比較

.NETのJsonはさまざまな目的に使用できます。 私の場合、これはASP.NET MvcアプリケーションでのAjaxリクエストへの回答の形成です。 もちろん、応答をJSONに変換することは最も薄い場所ではありませんが、この操作を高速化する方法を知りたいと思いました。 この記事は、.NET / Mono用の既存のJSONシリアライザーの詳細な概要ではありません。 まず、比較的単純なデータ構造のシリアル化に費やされる時間と、次にマッピングに興味がありました。 つまり、シリアル化が簡単かつ柔軟にプログラムされ、迅速に動作することを望みます。

次のシリアル化ツールが調査に含まれました。
  1. 単純な文字列連結
  2. JavaScriptSerializer(.NET Framework)
  3. DataContractJsonSerializer(.NET Framework 3.5)
  4. ニュートンJson.net( json.codeplex.com 、james.newtonking.com/ pages / json-net.aspx
  5. JsonEx( code.google.com/p/jsonexserializer
  6. Fluent Json( fluentjson.codeplex.com code.google.com/ p / fluent-json


パフォーマンスを測定するために、2種類のテストが実行されました。
テスト番号1。 シリアライザーが10,000回初期化され、同じオブジェクトがシリアル化されました。

テスト番号2。 シリアライザーが作成および初期化された1回。 シリアル化は10,000回実行されました。 このテストは、オブジェクトのタイプに関する情報を事前に受け取った「スマート」シリアライザーがより高速に変換を実行することを期待して考案されました。 場合によっては、予備的な初期化が不可能であり、さらにそのようなテストの結果はダッシュでマークされます。

テスト環境:
サブジェクトには、プラットフォームの一部である2つのクラスがあります。つまり、Monoと.NETでの作業に違いがある可能性があります。 私はUbuntuをメインの唯一のOSとして使用しているため、.NETのテストにはVirtualBox仮想マシンを使用しました。 そして正確には:

ストリング連結


まず、単純なToString()と連結による直列化のテスト結果を示します。 「本番」では、この方法はまれにしか正当化できません。 参照として使用するために検討します。 JSON形式の文字列をより高速に取得する方法を考えるのは困難です。
以下のテスト結果:
テスト番号1テスト番号2
.NET0.25秒-
モノ0.6秒-

明らかな理由により、テスト2を実行することは不可能です。

JavaScriptSerializer


JavaScriptSerializerは、.NET / MonoプラットフォームのSystem.Web.Script.Serialization名前空間にあります。 コード例:
var serializer = new JavaScriptSerializer();// string jsonResult = serializer.Serialize(Program.bookA);// 


JavaScriptConverter、RegisterConvertersクラスを使用して、さまざまなデータ型のシリアル化メソッドをオーバーライドする機能が宣言されています。 これは、たとえばDateTimeまたは列挙型の変換に役立ちます。 この機能を使用せずにテストを実施しました。

テスト結果:
テスト番号1テスト番号2
.NET4秒3.5秒
モノ5秒5秒


DataContractJsonSerializer


すぐに使用できる別のシリアライザーは、System.Runtime.Serialization.Json名前空間にあります。 使用中は、文字列ではなくストリームでシリアル化が行われることを除いて、前のものと大差ありません。 例:
 var serializer = new DataContractJsonSerializer(typeof(Book)); MemoryStream ms = new MemoryStream(); serializer.WriteObject(ms, Program.bookA); string jsonResult = Encoding.Default.GetString(ms.GetBuffer()); 


.NETとMonoでこのツールを使用する場合、違いがあります。 .NETでは、シリアル化可能なクラスとプロパティをそれぞれ[DataContract]属性と[DataMember]属性でマークする必要があります。 Monoでは、これらの属性はオプションです。
テスト結果は、違いは属性だけではないことを示しています。
テスト番号1テスト番号2
.NET1.5秒1.5秒
モノ34秒34秒

今後は、1.5秒と言います。これはすべての被験者の中で最高の時間で、34秒は最悪です。

流FluなJSON


このシリアライザーの利点(および誰と欠点)は、プロパティを柔軟にマッピングできることです。 ビジネスロジックレイヤーに属性を入力する必要はありません。サードパーティのライブラリを使用する場合は問題があります。 ビジネスロジック層のデータ構造をクライアント/サーバー交換のデータ構造に変換するための中間クラスは必要ありません。 主張されている「チップ」のもう1つは、大きなデータセットのマルチスレッド処理の可能性であり、これにより高いパフォーマンスが得られます。 私の場合ではありません。

以下のサンプルコードは、この仕組みを示しています。
 var serializer = Json.EnoderFor<Book>(config => config .MapType<Book>(map => map .AllFields() .Field<DateTime>(field => field.PubDate, pubDate => pubDate .EncodeAs<string>(value => value.ToShortDateString())) .Field<BookType>(field => field.Type, type => type .EncodeAs<int>(value => (int)value) .To("book_type"))) .MapType<Author>(map => map.AllFields()) .UseTidy(true) ); string jsonResult = serializer.Enode(Program.bookA); 


上記の例のように、シリアル化可能なデータ型に列挙型またはDateTimeのプロパティが含まれている場合、それらの変換を指定する必要があります。 Fluent Jsonは、それ自体で何をすべきか疑問に思っています。

テスト結果:
テスト番号1テスト番号2
.NET52.5秒9秒
モノ34秒10秒

JsonExSerializer


開発者の保証によると、このツールは、他のライブラリが提供しないオブジェクトの正確なシリアル化/逆シリアル化のために設計されています。 私にとってこれは最も重要なことではありません。スピードをテストします。 コード例:
 var serializer = new Serializer(typeof(Book)); var memoryStream = new MemoryStream(); serializer.Serialize(Program.bookA, memoryStream); var jsonResult = Encoding.Default.GetString(memoryStream.GetBuffer()); 


JsonExのジューシーな機能は、フォームのフォーマットとコメントを結果に追加することです:
 /* Created by JsonExSerializer Assembly: JsonTestConsole, Version=1.0.4347.32516, Culture=neutral, PublicKeyToken=null Type: JsonTestConsole.Book */ 

書式設定は、たとえば、設定をファイルに保存するときに役立ちます。この設定は、後でテキストエディターで編集できます。

テスト結果:
テスト番号1テスト番号2
.NET32秒8秒
モノ34秒10秒

ニュートンJSON.NET


機能の説明には、「。NETの組み込みJSONシリアライザーよりも高速な高性能」という興味深い行があります。 ニュートンを使用したサンプルコードは1行に収まります。
 string jsonResult = JsonConvert.SerializeObject(Program.bookA); 


初期化は必要ありませんが、非常に良い時間を示しています。
テスト番号1テスト番号2
.NET1.5秒-
モノ2秒-


おわりに


テスト結果は、両方の構成の時間(ミリ秒単位)の増加順にソートされています(列Kは、テストが「文字列連結」よりも遅い回数を示します)。

プラットフォームモノ.Net Framework
シリアライザーテスト番号1テスト番号2Kテスト番号1テスト番号2K
ストリング連結600-1250-1
ニュートンJSON.NET2,000-3.41,500-6
JavaScriptSerializer5,0004,0008.3 / 6.7170017006.8
JsonExSerializer34,00010,00056.7 / 16.74,0003,50016/14
流FluなJSON34,00010,00056.7 / 16.732,0008,000128/32
DataContractJsonSerializer34,00034,00056.7 / 56.71,5001,5006

この表は、Monoでアプリケーションを駆動する計画がある場合、またはプラットフォームが定義されていない場合、サードパーティライブラリNewton JSON.netを使用することをお勧めします。Win+ .NETとLinux + Monoの両方で良好な結果を示します。 ターゲットの.NETプラットフォームと属性バインディングが気にならない場合は、組み込みのDataContractJsonSerializerで十分です。 両方のオプションがあなたに合わないなら、あなたはあなた自身のライブラリを発明することができます-努力するべき多くがあります。

ここでテストコード: code.google.com/p/research-net-json/source/browse/Main.cs サードパーティのライブラリを個別にダウンロードする必要があります。もう一度リンクします:


UPD。 さらにいくつかのシリアライザーでテストを補足します( atdskyboyGuderian 、およびkekekeksに感謝します )。
プラットフォームモノ.Net Framework
シリアライザーテスト番号1テスト番号2Kテスト番号1テスト番号2K
新しいStringBuilder(400)550-0.9270-1
サービススタック1,300-2.21,200-4.8
Fast JSON2 600-4.31,200-4.8
ジェイロック8,200-13.79,200-36.8

ご覧のとおり、新しいリーダー-ServiceStackが登場しました。

PS間違いに気付いた場合、または他のライブラリを知っている場合は、書いてください。喜んで記事を補足します。

Source: https://habr.com/ru/post/J133778/


All Articles