1

私は以前にProtobuf-Netに関して関連しているがまだ異なる質問を投稿したので、ここに行きます:

誰か(特にマーク)が次のうちどれが最も速い可能性が高いかについてコメントできるかどうか疑問に思います:

(a)現在、シリアル化された組み込みデータ型をバイナリファイルに保存しています。具体的には、long(8バイト)と2つのfloat(2x 4バイト)です。これらの3つは、後で逆シリアル化された状態の1つのオブジェクトを構成します。longタイプは、ルックアップの目的でDateTimeTicksを表します。バイナリ検索を使用して、データリクエストの開始位置と終了位置を見つけます。次に、メソッドは、各チャンクが上記のトリプレット(1つの長さ、1つのフロート、1つのフロート)の多くのパケットで構成され、各トリプレットが常に16バイトの長さであることを認識して、データを1つのチャンク(開始位置から終了位置まで)にダウンロードします。したがって、取得されるトリプルの数は常に(endLocation --startLocation)/16です。次に、取得したバイト配列を反復処理し、(BitConverterを使用して)各組み込み型を逆シリアル化し、それぞれがトリプレットで構成される新しいオブジェクトをインスタンス化し、さらに処理するためにオブジェクトをリストに格納します。

(b)次のことを行う方が速いでしょうか?ルックアップの目的でインデックスとして機能する別のファイルを作成します(またはヘッダーを実装します)。次に、組み込み型の個々のバイナリバージョンを格納せず、代わりにProtbuf-netを使用して、上記のオブジェクトのリスト(=オブジェクトのソースとしてのint、float、floatのトリプレット)をシリアル化します。各リストには、正確かつ常に1日分のデータが含まれます(longはDateTimeTickを表すことに注意してください)。明らかに、各リストのサイズは異なります。したがって、各データ読み取り要求は丸1日の倍数しか要求しないため、インデックス検索の目的で別のファイルまたはヘッダーを生成するという私の考えです。ある日のシリアル化されたリストを取得したい場合は、インデックスを検索し、バイト配列を読み取り、Protobuf-Netを使用して逆シリアル化し、オブジェクトのリストを既に作成します。

データの大きさについてより良いアイデアを与えるために、各バイナリファイルは約3 GBの大きさであるため、何百万ものシリアル化されたオブジェクトが含まれています。各ファイルには、約1000日分のデータが含まれています。各データリクエストは、1日分のデータをリクエストできます。

あなたの意見では、生の処理時間の方が速いと思いますか?(b)を実装するために多くのコードを書く前に、いくつかの入力を収集したかったのですが、現在(a)で、マシン上で1秒あたり約150万個のオブジェクトを処理できます(プロセス=データ要求から返された逆シリアル化されたリストまで)オブジェクト)。

要約:バイナリデータがI / Oの読み取りを高速化し、アプローチ(a)または(b)を使用して逆シリアル化できるかどうかを尋ねています。

4

2 に答える 2

5

現在、シリアル化された組み込みデータ型をバイナリファイルに保存しています。具体的には、long(8バイト)と2つのfloat(2x 4バイト)です。

あなたが持っているのは(そして攻撃を意図していない)いくつかの非常に単純なデータです。生データを処理することに満足している場合(そしてあなたがそうであるように聞こえる場合)、これを処理する最適な方法は次のように思えます。オフセットは16のきれいな倍数などです。

一般に、プロトコルバッファ(protobuf仕様の単一の実装であるprotobuf-netだけでなく)は、より複雑な一連のシナリオを対象としています。

  • ネストされた/構造化されたデータ(たとえば、csv、つまり単純なレコードではなく、xml、つまり複雑なレコード)
  • オプションのフィールド(一部のデータはデータにまったく存在しない場合があります)
  • 拡張可能/バージョントレラント(予期しない値または半期待値のみが存在する可能性があります)
    • 特に、フィールドを壊すことなく追加/非推奨にすることができます
  • クロスプラットフォーム/スキーマベース
  • エンドユーザーがシリアル化の詳細に関与する必要がない場合

これは少し異なるユースケースです!この一部として、プロトコルバッファは小さいが必要なフィールドヘッダー表記(通常はフィールドごとに1バイト)を使用します。レコードは固定サイズではないため、レコードを分離するメカニズムが必要になります。これは通常、レコードごとにさらに2バイトです。記録。そして、最終的に、floatのプロトコルバッファ処理はIEEE-754であるため、まったく同じ2 x 4バイトを格納しますが、パディングが追加されます。長整数の処理は、プロトコルバッファ仕様内で固定サイズまたは可変サイズにすることができます。

あなたがしていることについて、そしてあなたは最速の生の処理時間を気にしているので、シンプルが最善のようです。「そのまま」にしておきます。

于 2012-06-19T08:25:43.600 に答える
1

各レコードが16バイトの固定サイズである限り、ランダムアクセスを実行できるため、インデックスと一緒に1日あたりの「チャンク」を使用することをお勧めします。ファイル内の毎日のオフセットを追跡するインデックスがある場合は、メモリマップトファイルを使用して、特定の日または日の範囲のデータの非常に高速なビューを作成することもできます。

プロトコルバッファの利点の1つは、値を圧縮するため、固定サイズのデータ​​を可変サイズにすることです(たとえば、ゼロの長い値は1バイトを使用して書き込まれます)。これにより、大量のデータへのランダムアクセスに関する問題が発生する可能性があります。

私はprotobufの専門家ではありませんが(Marcがここに記入してくれると思います)、Protocol Buffersは、全体として(または少なくとも全記録)。データの非常に大きなランダムアクセスストリームの場合、さまざまなレコードがさまざまな量で圧縮される可能性があると、単純なランダムアクセスを実行できなくなる可能性があるため、パフォーマンスが向上するとは思いません。

于 2012-06-19T08:19:56.713 に答える