web-dev-qa-db-ja.com

C#でバイトまたはショートの代わりにintを使用する理由

この問題に関していくつかのスレッドを見つけました。ほとんどの人は、byteまたはsmallintがモバイルアプリでない限りデータを処理する場合でも、ボード全体のc#コードでintを使用することを好むようです。理由がわかりません。 C#データ型を、データストレージソリューションと同じデータ型として定義する方が理にかなっていますか?

私の前提:型指定されたデータセット、Linq2SQLクラス、POCOを使用している場合、何らかの方法でデータ型の同期を維持しないと、コンパイラのデータ型変換の問題が発生します。私は本当にSystem.Convertを好きではありません。なぜなら、c#コードでボード全体でintを使用する方が簡単だからです。データベースへのインターフェースをクリーンに保つために、データベースとコードのデータを処理するために必要な最小のデータ型を常に使用しました。したがって、C#コードの75%は、intではなくbyteまたはshortを使用していると思います。これは、データベースに存在するためです。

可能性:これは、コードのすべてにintを使用するほとんどの人がSQLストレージデータ型にもintデータ型を使用し、データベースの全体的なサイズをあまり気にしない可能性があることを意味しますか?

気にする理由:私は自分で永遠に取り組んできたので、ベストプラクティスと標準のコーディング規約に精通したいだけです。

59
Breadtruck

パフォーマンスに関しては、ほとんどすべての場合でintの方が高速です。 CPUは、32ビット値で効率的に動作するように設計されています。

短い値は処理が複雑です。たとえば、1バイトを読み取るには、CPUはそれを含む32ビットブロックを読み取ってから、上位24ビットをマスクする必要があります。

バイトを書き込むには、宛先の32ビットブロックを読み取り、下位8ビットを目的のバイト値で上書きし、32ビットブロック全体を再度書き込む必要があります。

もちろん、スペースに関しては、より小さなデータ型を使用して数バイトを節約します。したがって、数百万行のテーブルを構築する場合は、短いデータ型を検討する価値があります。 (そして、あなたがあなたのデータベースでより小さなデータ型を使うべきである理由は同じかもしれません)

正確性に関しては、intは簡単にはオーバーフローしません。 think値がバイトに収まり、将来のある時点でコードに無害に見える変更が行われると、大きな値が格納されることになりますか?

これらが、intがすべての整数データのデフォルトのデータ型である理由の一部です。実際にマシンのバイトを格納する場合にのみ、byteを使用してください。実際に16ビット整数値を指定するファイル形式やプロトコルなどを扱っている場合にのみ、shortを使用してください。一般的に整数を扱うだけの場合は、整数にします。

81
jalf

私はわずか6年遅れていますが、他の人を助けることができるかもしれません。

ここに私が使用するいくつかのガイドラインがあります:

  • データが将来適合しない可能性がある場合は、より大きなint型を使用してください。
  • 変数がstruct/classフィールドとして使用されている場合、デフォルトでは、32ビット全体を占めるようにデフォルトでパディングされるため、byte/int16を使用してもメモリは節約されません。
  • 変数の寿命が短い場合(関数内など)、小さいデータ型はあまり役に立ちません。
  • 「byte」または「char」は、データをより適切に説明できる場合があり、誤って大きな値が割り当てられていないことを確認するためのコンパイル時チェックを実行できます。例えばバイトを使用して日(1-31)を格納し、それに1000を割り当てようとすると、エラーが発生します。
  • 変数が約100以上の配列で使用されている場合は、意味がある限り、より小さなデータ型を使用します。
  • byte配列とint16配列は、int(プリミティブ)ほどスレッドセーフではありません。

誰も取り上げなかったトピックの1つは、制限されたCPUキャッシュです。 CPUがより多くのプログラムをより高速のL1/L2/L3キャッシュに収めることができるため、小さいプログラムは大きいプログラムよりも速く実行されます。

Int型を使用すると、CPU命令が少なくなる可能性がありますが、データメモリの割合が高くなり、CPUキャッシュに収まらなくなります。命令は安価に実行できます。最近のCPUコアは、クロックサイクルごとに3〜7命令を実行できますが、一方、1回のキャッシュミスは、RAMに到達する必要があるため、1000〜2000クロックサイクルかかる可能性があります。

メモリが節約されると、キャッシュから絞り出されないため、残りのアプリケーションのパフォーマンスが向上します。

バイト配列とint配列の両方を使用して、ランダムな順序でランダムデータにアクセスする簡単な合計テストを行いました。

const int SIZE = 10000000, LOOPS = 80000;
byte[] array = Enumerable.Repeat(0, SIZE).Select(i => (byte)r.Next(10)).ToArray();
int[] visitOrder = Enumerable.Repeat(0, LOOPS).Select(i => r.Next(SIZE)).ToArray();

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
int sum = 0;
foreach (int v in visitOrder)
    sum += array[v];
sw.Stop();

時間(ティック)での結果は次のとおりです:(x86、リリースモード、デバッガーなし、.NET 4.5、I7-3930k)(小さいほど良い)

________________ Array Size __________________
       10  100   1K   10K  100K    1M   10M 
byte: 549  559  552   552   568   632  3041  
int : 549  566  552   562   590  1803  4206
  • cPUでバイトを使用して100万個のアイテムにランダムにアクセスすると、パフォーマンスが285%向上しました。
  • 10,000未満はほとんど目立ちません。
  • この基本的な合計テストでは、intがbyteより速くなることはありませんでした。
  • これらの値は、キャッシュサイズが異なるCPUによって異なります。

最後に、時々私は、現在オープンソースの.NETフレームワークを見て、Microsoftの専門家が何をしているのかを調べます。 .NETフレームワークは、驚くほど少ないバイト/整数16を使用します。実際には見つかりませんでした。

19
Sunsetquest

ストレージ容量の点で大きな違いが生じる前に、数十億行を処理する必要があります。 3つの列があり、バイトに相当するデータベースタイプを使用する代わりに、intに相当するものを使用するとします。

これにより、行ごとに3(列)x 3(追加のバイト)、または行ごとに9バイトが得られます。

つまり、「数百万行」(300万行としましょう)の場合、27メガバイトのディスクスペース全体が余分に消費されます。幸いにも1970年代にはもう住んでいないので、これについて心配する必要はありません:)

上記のように、マイクロ最適化を停止します-非常に、非常に非常に大きなものを扱っていない限り、帯域幅/ディスクスペースのコストよりも、整数のような異なる数値型との間の変換におけるパフォーマンスへの影響がはるかに大きくなります。データセット。

8
Jon Grant

ほとんどの場合、「いいえ」です。

何億もの行を処理することを前もって知っていなければ、それはマイクロ最適化です。

ドメインモデルに最も適合するものを実行します。後で、パフォーマンスの問題が発生した場合は、ベンチマークとプロファイルを実行して、問題が発生している場所を特定します。

7
Mitch Wheat

ジョン・グラントらを信じていなかったわけではありませんが、「ミリオン・ロー・テーブル」を自分で見なければなりませんでした。テーブルには1,018,000があります。 11 tinyintカラムと6 smallintカラムをintに変換しました。すでに5 intと3 smalldatetimeがありました。 4つの異なるインデックスがさまざまなデータ型の組み合わせを使用していましたが、明らかに新しいインデックスはすべてint列を使用しています。

変更を加えるだけで、インデックスなしでベーステーブルのディスク使用量を計算するのに40 MBしかかかりません。インデックスを追加して全体を変更したところ、全体の差はわずか30 mbでした。インデックスのサイズがもっと大きくなると思ったので驚いた。

つまり、さまざまなデータタイプをすべて使用する手間は30 MBです。私はINTの土地に出発しました。この肛門の保持力のあるプログラマーを、整数変換のないまっすぐで幸せな至福の生活に戻してくれた皆さんに感謝します...

5
Breadtruck

どこでもintが使用されている場合、キャストや変換は必要ありません。これは、複数の整数サイズを使用することで節約できるメモリよりも大きなメリットです。

それは人生をより単純にするだけです。

4
Robert Harvey

.NETランタイムはInt32用に最適化されています。以前のディスカッションを 。NET Integer vs Int16? で参照してください

4
Dan Diplo