10

ユーザーが処理する変数を指定できるコンソールアプリケーションがあります。これらの変数には、string、double、およびlongの3つのフレーバーがあります(doubleおよびlongは、最も一般的に使用されるタイプです)。ユーザーは好きな変数を好きな順序で指定できるので、私のシステムはそれを処理できなければなりません。この目的のために、私のアプリケーションでは、これらをオブジェクトとして保存し、必要に応じてキャスト/アンキャストしていました。例えば:

public class UnitResponse
{
    public object Value { get; set; }
}

私の理解では、ボックス化されたオブジェクトは、標準の値型よりも少し多くのメモリ(約12バイト)を使用します。

私の質問は、これらの値を格納するために動的キーワードを使用する方が効率的でしょうか?それはボクシング/アンボクシングの問題を回避するかもしれません、そしてそれがより効率的であるならば、これはパフォーマンスにどのように影響しますか?

編集

いくつかのコンテキストを提供し、「これを心配するのに十分なRAMを使用していることを確認してください」を防ぐために、最悪の場合、心配するデータポイントは420,000,000個あります(60変数* 7,000,000レコード)。これは、各変数(いくつかのブール値などを含む)について私が保持している他のデータの束に追加されます。したがって、メモリの削減は大きな影響を及ぼします。

4

4 に答える 4

19

さて、ここでの本当の質問は、「メモリに保存している巨大なデータセットがあります。時間とメモリ空間の両方でそのパフォーマンスを最適化するにはどうすればよいですか?」です。

いくつかの考え:

  • あなたはボクシングを憎み、恐れるのは絶対に正しいです。ボクシングには大きなコストがかかります。まず、はい、ボックス化されたオブジェクトは余分なメモリを消費します。次に、ボックス化されたオブジェクトは、スタックやレジスタではなく、ヒープに格納されます。第三に、それらはガベージコレクションです。これらのオブジェクトのすべてをGC時に問い合わせて、別のオブジェクトへの参照が含まれているかどうかを確認する必要がありますが、これは決して含まれません。これは、GCスレッドで多くの時間を要します。あなたはほぼ確実にボクシングを避けるために何かをする必要があります。

ダイナミックではありません。それはボクシングに加えて他の多くのオーバーヘッドです。(C#の動的は、他の動的ディスパッチシステムと比較して非常に高速ですが、絶対的には高速でも小さくもありません)。

グロスですが、Cの共用体のように、レイアウトがさまざまなフィールド間でメモリを共有する構造体の使用を検討できます。そうすることは本当にグロスであり、まったく安全ではありませんが、このような状況では役立ちます。「StructLayoutAttribute」のWeb検索を実行します。チュートリアルがあります。

  • 長い、二重、または文字列、本当に?int、float、stringにすることはできませんか?データは本当に数十億を超えるか、小数点以下15桁まで正確ですか?intとfloatは、99%のケースでその役割を果たしませんか?彼らは半分のサイズです。

通常、float over doubleを使用することはお勧めしません。これは、誤った経済であるためです。4バイトの節約が違いを生むように、人々は1つの番号を持っているときにこのように節約することがよくあります。4200万フロートと4200万ダブルの違いはかなりのものです。

  • 利用できるデータに規則性はありますか?たとえば、4,200万件のレコードのうち、たとえば、longごとに100000個の実際の値、doubleごとに100000個の値、stringごとに100000個の値しかないとします。その場合、longs、doubles、stringsに対して何らかのインデックス付きストレージを作成すると、各レコードは整数を取得します。下位ビットはインデックスであり、上位2ビットはどのストレージから取得するかを示します。これで、それぞれにintを含む4,200万件のレコードがあり、値は別の場所にコンパクトな形式で格納されています。

  • ブール値を1バイトのビットとして格納します。'emを取り出すためにビットシフトを行うためのプロパティを記述します。そのようにして数バイト節約してください。

  • メモリは実際にはディスクスペースであることを忘れないでください。RAMは、その上にある便利なキャッシュです。データセットが大きすぎてRAMに保持できない場合は、何かがデータセットをディスクにページアウトし、後で読み戻すことになります。それはあなたかもしれませんし、オペレーティングシステムかもしれません。オペレーティングシステムよりもデータの局所性についてよく知っている可能性があります。データを便利なページ可能な形式(bツリーなど)でディスクに書き込むことができ、ディスク上にデータを保持し、必要なときにのみメモリに取り込むことをより効率的に行うことができます。

于 2011-01-29T16:51:53.307 に答える
14

ここで間違ったものを見ているのではないかと思います。ダイナミックが何をするかを覚えておいてください。実行時に、処理中にコンパイラを再起動します。コンパイラー用に数十万バイトのコードをロードし、すべての呼び出しサイトで、動的操作ごとに新たに発行されたILの結果を含むキャッシュを発行します。あなたは8を節約するために数十万バイトを費やしています。それは悪い考えのようです。

そしてもちろん、あなたは何も保存しません。「ダイナミック」とは、派手な帽子をかぶった「オブジェクト」のことです。「動的」オブジェクトは引き続きボックス化されます。

于 2011-01-27T23:44:18.017 に答える
3

いいえ 。オブジェクト自体の保存方法ではなく、オブジェクトに対する操作の実行方法dynamicに関係します。この特定のコンテキストでは、値型は引き続きボックス化されます。

また、このすべての作業は、オブジェクトごとに本当に12バイトの価値がありますか?確かに、RAMを数キロバイト(もしそうなら)節約するよりも、あなたの時間のより良い使い方がありますか?プログラムによるRAM使用量が実際に問題であることを証明しましたか?

于 2011-01-27T23:39:13.387 に答える
2

いいえ。Dynamicは単にオブジェクトとして保存します。

これは、ほとんどまたはまったくメリットがないマイクロ最適化である可能性があります。これが本当に問題になる場合は、物事をスピードアップするために使用できる他のメカニズム(ジェネリック)があります。

于 2011-01-27T23:38:04.127 に答える