.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
.NET 0.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
.NET 4秒 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
.NET 1.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
.NET 52.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
.NET 32秒 8秒
モノ 34秒 10秒


ニュートンJSON.NET



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

 string jsonResult = JsonConvert.SerializeObject(Program.bookA);
      
      







初期化は必要ありませんが、非常に良い時間を示しています。

テスト番号1 テスト番号2
.NET 1.5秒 -
モノ 2秒 -




おわりに



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



プラットフォーム モノ .Net Framework
シリアライザー テスト番号1 テスト番号2 K テスト番号1 テスト番号2 K
ストリング連結 600 - 1 250 - 1
ニュートンJSON.NET 2,000 - 3.4 1,500 - 6
JavaScriptSerializer 5,000 4,000 8.3 / 6.7 1700 1700 6.8
JsonExSerializer 34,000 10,000 56.7 / 16.7 4,000 3,500 16/14
流FluなJSON 34,000 10,000 56.7 / 16.7 32,000 8,000 128/32
DataContractJsonSerializer 34,000 34,000 56.7 / 56.7 1,500 1,500 6


この表は、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 テスト番号2 K テスト番号1 テスト番号2 K
新しいStringBuilder(400) 550 - 0.9 270 - 1
サービススタック 1,300 - 2.2 1,200 - 4.8
Fast JSON 2 600 - 4.3 1,200 - 4.8
ジェイロック 8,200 - 13.7 9,200 - 36.8


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



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



All Articles