37

Marc Gravellによって開発された .NET 用のプロトコル バッファ ソリューションがなぜこれほど高速なのかを理解したいと思います。

元の Google ソリューションがどのようにパフォーマンスを達成したかは理解できます。オブジェクトのシリアル化用に最適化されたコードを事前に生成します。私はいくつかのシリアル化を手作業で書きましたが、リフレクションを回避すれば、この方法で非常に高速なコードを記述できることを知っています。しかし、Marc のライブラリは、属性を使用するランタイム ソリューションであり、コードを生成しません。それで、それはどのように機能しますか?

4

2 に答える 2

47

protobuf-net は戦略パターンを使用します。必要に応じて (型ごとに 1 回のみ) リフレクションを使用して型を調べ、シリアル化と逆シリアル化に使用できる一連のシリアライザー (共通インターフェイスに基づく) を構築します。シリアライザーのセット。

その中で、メンバーと話すときにリフレクションを賢明に利用しようとします。Delegate.CreateDelegateプロパティとの対話に使用し、 DynamicMethod(およびカスタム IL) フィールドとの対話に使用します (可能な場合。ターゲット フレームワークによって異なります)。これは、(非常に遅い)だけではなく、常に既知のデリゲート型と通信していることを意味します。DynamicInvoke

気が狂うことなく、コードには次の点でいくつかの最適化があります (おそらく読みやすさを犠牲にして)。

  • (入力/出力ストリームの)ローカルbyte[]バッファリング
  • (リストなどではなく) 固定サイズの配列を使用する。おそらく多すぎる
  • ジェネリックを使用してボクシングを回避する
  • バイナリ処理ループに関する多数の微調整/ひねり/その他

後から考えると、ジェネリックの点で間違いを犯したと思います。複雑さは、ジェネリックをシステムに強制すると、いくつかの場所で形が崩れ、コンパクトなフレームワークで(複​​雑なモデルの場合)いくつかの大きな問題を積極的に引き起こすことを意味しました。

ジェネリック インターフェイスを使用してこれをリファクタリングし、代わりに (適切なフレームワークの場合) をより多く使用するILGenerator(私の最初の選択は でしExpressionたが、それはより高いフレームワーク バージョンを強制する) いくつかの設計を (私の頭の中でのみ)持っています。ただし、問題は、これが機能するまでにかなりの時間がかかることであり、ごく最近まで私はかなり忙殺されていました

最近、protobuf-net に再び時間を費やすことができたので、リクエストなどのバックログをクリアして、すぐに開始できることを願っています。また、リフレクション以外のモデルで動作させることも意図しています(つまり、ワイヤ マッピングを個別に記述します)。


生成されたコードを生成しません

生成されたコードを使用する場合は、2 つの (オプションの) codegen ルートがあることも明確にする必要があります。protogen.exe またはVS アドインを使用すると、.proto ファイルからコードを生成できます。ただし、これは必須ではありません。主に、既存の.protoファイルがある場合、またはコントラクト優先開発のために別の言語 (C++ など) と相互運用する場合に役立ちます。

于 2009-11-12T16:53:41.603 に答える
-2

その性能は非常に良いです!

私が行ったprotobufを含むさまざまなフォーマット間の包括的な比較を見ることができます - http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text /

この比較には、大小のデータ サンプルとさまざまな形式が含まれます。

私の投稿のテストの1つ- ここに画像の説明を入力

于 2014-03-31T23:21:58.690 に答える