今後のプロジェクトで行うことを考えている一部のキャッシングについては、Javaシリアル化について考えています。つまり、使用すべきですか?
今、私は以前、さまざまな理由でカスタムシリアル化と逆シリアル化(Externalizable)を書いてきました。最近では相互運用性がさらに問題になり、.Netアプリケーションと対話する必要性が予測できるため、プラットフォームに依存しないソリューションを使用することを考えました。
GPBの高性能使用の経験はありますか? Javaのネイティブシリアル化と速度と効率の点でどのように比較されますか?あるいは、検討する価値のある他のスキームはありますか?
プロトコルバッファとJavaのネイティブシリアル化を速度の面で比較したことはありませんが、相互運用性のためにJavaのネイティブシリアル化は非常に重要です。また、ほとんどの場合、プロトコルバッファほどスペースに関して効率的ではありません。もちろん、保存できるものや参照などの点で多少柔軟性があります。プロトコルバッファーは、目的に合わせて非常に優れており、必要に応じて最適です-しかし、相互運用性のために明らかな制限があります(と他のこと)。
最近、Java and .NETでプロトコルバッファベンチマークフレームワークを投稿しました。Javaバージョンは メインGoogleプロジェクト ( ベンチマークディレクトリ )で、.NETバージョンは my C#ポートプロジェクト にあります。PB速度をJavaと比較する場合相互運用に興味がある場合は、ネイティブJavaシリアル化(または.NETネイティブバイナリシリアル化)を改めて考えないでください。
ただし、プロトコルバッファー以外にも相互運用可能なシリアル化には他のオプションがあります- Thrift 、 [〜#〜] json [〜#〜] および [〜#〜] yaml [〜#〜] 心に湧き、そして間違いなく他のものがあります。
編集:さて、相互運用性はそれほど重要ではないので、シリアル化フレームワークから必要なさまざまな品質をリストアップする価値があります。あなたが考える必要があることの1つはバージョン管理です-これはPBが逆方向と順方向の両方をうまく処理するように設計されている別のことです(したがって、新しいソフトウェアは古いデータを読み取ることができ、逆も同様です)-もちろん、提案されたルールに従う場合:)
Javaパフォーマンスvsネイティブシリアライゼーションに注意を払おうとしたが、とにかくPBの方が高速であることを知って驚くことはないだろう。ベンチマークでは、サーバーをVMになるように2倍以上高速サンプルデータのシリアル化および非シリアル化で示しました。
サンプルのパフォーマンス数値、2つのメッセージ(1つは228バイト、1つは84750バイト)のシリアライズとデシリアライズのように、サーバーVMを使用してラップトップで次の結果を得ました。
ベンチマークgoogle.message1.datファイルを使用したベンチマーク.GoogleSize $ SizeMessage1 バイト文字列へのシリアル化:30.16秒で2581851回の繰り返し。 18.613789MB/s バイト配列にシリアル化:29.842秒で2583547回の繰り返し。 18.824497MB/s メモリストリームへのシリアル化:30.125秒で2210320回の繰り返し。 15.953759MB/s バイト文字列からデシリアライズ:30.088秒で3356517回の反復。 24.256632MB/s バイト配列からデシリアライズ:29.958で3356517回の反復。 24.361889MB/s メモリストリームからデシリアライズ:29.821sで2618821回の反復。 19.094952MB/s ベンチマークgoogle_message1.datを使用したベンチマークGoogleSpeed $ SpeedMessage1 バイト文字列にシリアル化:29.978秒で17068518回の繰り返し。 123.802124MB/s バイト配列にシリアル化:30.043sで17520066回の反復。 126.802376MB/s メモリストリームへのシリアル化:30.076sで7736665回の繰り返し。 55.93307MB/s バイト文字列からデシリアライズ:30.073秒で16123669回の反復。 116.57947MB/s バイト配列からデシリアライズ:30.109sで16082453回の反復。 116.14243MB/s メモリストリームからのシリアル化解除:30.03sで7496968回の繰り返し。 54.283176MB/s ベンチマークgoogle.message2.datでベンチマークGoogleSize $ SizeMessage2 バイト文字列にシリアル化:30.034秒で6266回の繰り返し。 16.826494MB/s バイト配列にシリアル化:30.027sで6246回の反復。 16.776697MB/s メモリストリームへのシリアル化:29.916秒で6042回の反復。 16.288969MB/s バイト文字列からデシリアライズ:29.819秒で4675回の反復。 12.644595MB/s バイト配列からデシリアライズ:30.093秒で4694回の反復。 12.580387MB/s メモリストリームからデシリアライズ:29.579秒で4544回の反復。 12.389998MB/s ベンチマークベンチマーク。GoogleSpeed$ SpeedMessage2ファイルgoogle_message2.dat バイト文字列にシリアル化:30.055秒で39562回。 106.16416MB/s バイト配列にシリアル化:30.178sで39715回の繰り返し。 106.14035MB/s メモリストリームへのシリアル化:30.032秒で34161回の反復。 91.74085MB/s バイト文字列からデシリアライズ:29.794で36934回の反復。 99.98019MB/s バイト配列からデシリアライズ:29.915秒で37191回の反復。 100.26867MB/s メモリストリームからデシリアライズ:29.846秒で36237回の反復。 97.92251MB/s
「速度」と「サイズ」は、生成されたコードが速度とコードサイズのどちらに最適化されているかです。 (シリアル化されたデータはどちらの場合も同じです。「サイズ」バージョンは、多くのメッセージが定義されていて、コードに大量のメモリを使用したくない場合に提供されます。)
ご覧のとおり、小さなメッセージの場合はvery fast-500を超える小さなメッセージがシリアル化または非シリアル化されますper millisecond。 87Kのメッセージでも、1メッセージあたり1ミリ秒未満しかかかりません。
もう1つのデータポイント:このプロジェクト:
http://code.google.com/p/thrift-protobuf-compare/
pBでのJavaシリアル化を含む、小さなオブジェクトの期待されるパフォーマンスのアイデアを提供します。
プラットフォームによって結果は大きく異なりますが、いくつかの一般的な傾向があります。
[〜#〜] fst [〜#〜] もご覧ください。組み込みJDKシリアル化のドロップイン代替品で、高速で出力が小さいはずです。
私が最近行った頻繁なベンチマークの生の推定:
100%=バイナリ/構造ベースのアプローチ(SBE、fst-structなど)
〜10%-35%プロトバフと誘導体
FSTやKRYOなどの〜10%-30%高速シリアライザー
〜2%-15%JDKシリアル化
〜1%-15%高速JSon(例:ジャクソン)
0.001-1%フルグラフJSon/XML(JSON.ioなど)
これらの数値は、非常に大雑把な印象を与えるためのものです。パフォーマンスは、シリアル化/ベンチマークされるデータ構造に大きく依存することに注意してください。そのため、単一の単純なクラスベンチマークはほとんど役に立ちません(ただし、人気があります:たとえば、ユニコードを無視し、コレクションがないなど)。
また見なさい
http://Java-is-the-new-c.blogspot.de/2014/12/a-persistent-keyvalue-server-in-40.html
http://Java-is-the-new-c.blogspot.de/2013/10/still-using-externalizable-to-get.html
PBとネイティブJava速度と効率の直列化を混同している場合は、PBを選択してください。
一部の開発者はThriftを推奨していますが、私は「Googleを信じている」ためGoogle PBを使用します:-) ..とにかく、一見の価値があります。 http://stuartsierra.com/2008/07/10/thrift -vs-protocol-buffers
高性能とはどういう意味ですか?ミリ秒のシリアル化が必要な場合は、最も単純なシリアル化アプローチを使用することをお勧めします。サブミリ秒が必要な場合は、バイナリ形式が必要になる可能性があります。 10マイクロ秒よりずっと短い時間が必要な場合は、カスタムシリアル化が必要になる可能性があります。
シリアル化/逆シリアル化のベンチマークはあまり見ていませんが、シリアル化/逆シリアル化の200マイクロ秒未満をサポートするものはほとんどありません。
プラットフォームに依存しない形式では、コストがかかります(ユーザーの努力とレイテンシ)ので、パフォーマンスとプラットフォームのどちらを独立させるかを決定する必要があります。ただし、必要に応じて切り替える構成オプションとして両方を使用できない理由はありません。
ここにその日の提案があります:-)(あなたは私の頭の中で私が今試したい何かを微調整しました)...
これを介してキャッシュソリューション全体を使用できる場合は、動作する可能性があります: Project Darkstar 。これは非常に高性能なゲームサーバーとして設計されており、特に読み取りが高速になります(キャッシュに適しています)。 JavaおよびC APIがあるため、Javaを使用してオブジェクトを保存し、読むことができると信じています(それを見てから長い時間が経っていると考えていました)。それらをCに戻し、逆も同様です。
他に何もなければ、今日読むべきものを提供します:-)
ワイヤフレンドリーなシリアル化を行うには、Externalizableインターフェイスの使用を検討してください。巧妙に使用すると、特定のフィールドを最適にマーシャリングおよびアンマーシャリングする方法を決定するための詳細な知識が得られます。ただし、各オブジェクトのバージョン管理を正しく管理する必要があります-マーシャリング解除は簡単ですが、コードがV1をサポートするときにV2オブジェクトを再マーシャリングすると、アプリが壊れたり、情報が失われたり、データが破損したりします正しく処理できません。最適なパスを探している場合、妥協することなく問題を解決できるライブラリはないことに注意してください。一般に、ライブラリはほとんどのユースケースに適合し、アクティブなオープンソースプロジェクトを選択した場合、ユーザーの入力なしで時間の経過とともに適応および強化されるという追加の利点があります。また、パフォーマンスの問題を追加したり、バグを導入したり、まだ影響していないバグを修正したりすることもあります。