ブール値がcharよりも多くのメモリを消費するのはなぜですか?
質問
.NETフレームワークでブールが4バイトとchar 2バイトを消費するのはなぜですか?ブール値は1ビットを使用するか、少なくとも1文字より小さくする必要があります。
解決
これは、メモリ調整の問題です。 4バイト変数は、2バイト変数よりも高速に動作します。これが、カウンターなどにbyteまたはshortの代わりにintを使用する必要がある理由です。
メモリが速度よりも重要な場合にのみ、2バイト変数を使用する必要があります。これが、char(.NETではUnicode)が4バイトではなく2バイトを使用する理由です。
他のヒント
boolean
について
他のほとんどの答えは間違っています-コンパイラーがループカウンターをintに固執する必要があるのは、コンパイラーがバイトを4バイト幅にできる理由ではなく、アライメントと速度が理由です。実際、すべての推論は、ブールと同様にバイトとショートにも適用されます。
少なくともC#では、bool(またはSystem.Boolean)は1バイト幅の組み込み構造であり、自動的にボックス化できます。したがって、オブジェクト(少なくとも2つのメモリワードを表す必要があります。つまり、それぞれ32/64ビット環境で8/16バイト)、フィールド(少なくとも1バイト)に加えて、それを指す1つのメモリワード、つまり合計で少なくとも13/25バイト。
これはまさに「C#プリミティブ型」に関するGoogleの最初のエントリです。 http://msdn.microsoft.com/en-us/ library / ms228360(VS.80).aspx
引用されたリンク( http://geekswithblogs.net/cwilliams /archive/2005/09/18/54271.aspx )は、CLI標準によるブール値には1バイトが必要であることも示しています。
ただし、実際には、これが表示される唯一の場所はブール値の配列上です-nブール値はnバイトかかります。その他の場合、1つのブール値に4バイトかかる場合があります。
- 構造内で、ほとんどのランタイム(Javaでも)は、パフォーマンスのためにすべてのフィールドを4バイト境界に揃えます。組み込みデバイス用のMonty JVMは賢明です。フィールドを最適に並べ替えると思います。
- インタープリターのローカルフレーム/オペランドスタックでは、ほとんどの実装で、パフォーマンスのために、1つのスタックエントリは1メモリワード幅です(.NETでは、ダブルとロングをサポートするために64ビット幅でなければなりません。 .NETでは、Javaの2ではなく1つのスタックエントリのみを使用します)。 JITコンパイラーは、追加のオーバーヘッドがそれだけの価値がある場合、フィールドに並べ替えることでパフォーマンスに影響を与えずに他の変数を揃えたまま、ブールローカルに1バイトを代わりに使用できます。
char
について
char
は2バイトです。これは、国際化のサポートが必要な場合、内部で2バイト文字を使用することが最も安全な方法だからです。これは、Unicodeのサポートを選択することに直接関連するのではなく、UTF-16およびBasic Multilingual Planeに固執する選択に関連しています。 JavaおよびC#では、1つの論理文字がchar型の変数に収まると常に想定できます。
これは、32ビット環境では、CPUが32ビット値を8ビットまたは16ビット値よりも速く処理できるため、これは速度/サイズのトレードオフだからです。メモリを節約する必要があり、boolが大量にある場合は、 uint を使用して、ブール値を4バイトの uint のビットとして保存します。 文字は16ビットUnicode文字を格納するため、2バイト幅です。
メモリストレージのわずかな違いに関係なく、true / false yes / no値にブール値を使用することは、意図をより正確に反映するため、開発者(1年後にコードを再検討する必要がある場合は自分を含む)にとって重要です。コードを理解しやすくすることは、2バイトを節約するよりもはるかに重要です。
意図をより正確にコードに反映させることは、コンパイラの最適化が悪影響を与える可能性を減らします。このアドバイスは、プラットフォームとコンパイラーを超えています。
また、メンテナンス可能なコードを記述するためにブール値を使用する必要があります。何かがブール値であることがコードで見ている場合、ブール値としてcharを使用していることを把握するためにメモリを節約する価値があります。
これを見つけました:"実際、ブール値は2バイトではなく4バイトです。理由は、CLRがブール値をサポートしているからです。 32ビット値を操作する方がはるかに効率的であるため、時間/スペースのトレードオフは一般に価値があるので、それがそれだと思います。たくさんのビットを一緒に詰め込む必要がある場合は、ビットベクトルクラスを使用する必要があります(場所を忘れてください)"
Paul Wickによる http://geekswithblogs.net /cwilliams/archive/2005/09/18/54271.aspx
まず、プロファイラーを使用して、メモリのどこに問題があるかを判断する必要があります。私見
メモリは、ビットの配列が大きい場合にのみ問題になります。その場合、System.Collections.BitArrayクラスを使用できます。
Windowsと.Netが Unicode (UTF 16)は、内部文字セットとしての開始以来。 UTF 16 は、文字ごとに2バイト、または文字ごとに2バイトの単語のペアを使用しますが、必要に応じて可変幅エンコードです。
" Basic Multilingual Plane(BMP)の文字の場合、結果のエンコードは単一の16ビットワードです。他のプレーンの文字の場合、エンコードの結果、16ビットワードのペアが生成されます。
ブール値に関する私の推測では、デフォルトのレジスタは32ビットであるため4バイトであり、これは.Netがビット単位演算を使用しない限り効率的に論理演算を行うことができる最小サイズです。