2015-12-18 10 views
5

クラスを介してstructを使用するとどのくらいのパフォーマンスが得られますか?私はクラス以上の構造体の最大限の使用に焦点を当ててアプリケーションを設計する必要がありますか?c#struct vsクラスperformace、デザインフォーカス

クラスを構造体に変換し、関数を別の静的クラスに移動することは可能です。

+1

構造体を使用すると、構造体のフィールドにアクセスするための参照の逆参照を避けることができますが、構造体を渡す必要があるときはいつでも、参照によって明示的に渡さない限りコピーされます。これは便利ですが、クラスに対する構造体のブランケットの使用は、あなたのコードに有害な可能性が非常に高いでしょう。 –

+0

さらに重要なことは、動的割り当てを避けることです。構造体、つまり値型は、intとよく似た動作をします。それらを作成すると、動的割り当てよりも大幅に安価なローカルまたは静的メモリーになります。欠点は、Martinが言っているように、値が代入、戻りなどのためにコピーされるということです。参照を返すよりも大きなオブジェクトの場合にだけより高価です。 –

答えて

3

(別の答えに記載されている)MSDNの勧告は、いくつかのガイダンスを提供しています。パフォーマンスのためには、その使用法と、構造体とクラスの違いがどこにあるかを考慮する必要があります。最も重要なことは、タイプが実際の値タイプである場合にのみ構造体を使用することです。つまり、の値の意味です。値型にクラスを使用するか、参照型でなければならない何かの構造体を使用すると、意図しないコピーや意図しない参照ですぐに混乱する結果になります。また、構造体は常に不変でなければならないことに注意してください。

これらの基本規則は無視してください(大文字小文字の区別:このフレームワークはList.Enumerator構造体の規則を破ります)。クラス対構造体のための

パフォーマンス・注意事項:

あなたがメソッドの引数として、あなたの構造体を渡す場合は、構造体のコピーを毎回作成されます。これは、16バイトを超える構造体を作成しないことを推奨している理由です。上記のシナリオで

double Distance(Vector3D a, Vector3D b) // Copies both 24-byte structs 
{ 
    return Math.Sqrt((a.X - b.X *....); 
} 

、3倍の3Dベクトルは、24バイトになるだろうし、推奨さ16よりも大きいであろうが、それは明らかに値型であるので、私はまだ構造体は、理にかなっていると主張したいです特に構造体である2つの2倍(16バイト)のVector2Dを持っています!

構造体を効率的に使用するための鍵は、パフォーマンスが実際に輝く場所で、キャッシュローカリティに使用し、多くの割り当てを避けることです。上記のVectorの例を再利用するには、このメソッドを使用している場合

double AverageDistanceFromOrigin(Vector3D[] points) // Single reference passed 
{ 
    double sum = 0.0; 
    for(...)           
     sum += Math.Sqrt(points[i].X... + ... + ...) // No copies 
    return sum/points.Length; 
} 

構造体の方がパフォーマンスが良いことがあります。その理由は、メソッドに単一の参照(配列)を渡しているので、呼び出しごとに構造体をコピーするための余分なオーバーヘッドはありません(このメソッドは配列の各エントリに対してdistanceメソッドを呼び出さないことに注意してください) 。

struct-of-structsは、[x1、y1、x2、y2、...]のようにメモリ内に連続して配置されているので、CPUはロードします。 16の座標を一度にキャッシュに格納するため、キャッシュミスがほとんど発生しません。これをclass Vector3Dの実装と比較すると、ベクトルの配列が割り当てられ、配列の各エントリはでもというヒープ割り当てが必要な参照となり、後でガベージコレクションされます。配列は、ヒープ内の任意のアドレスを持つ可能性のある参照の配列[v1へのref、v2へのref、v3へのref]を持ち、互いに隣に座っていない可能性があります。これは、構造体の場合よりも多くのキャッシュミスにつながります。あなたのタイプは値のセマンティクス(およびその逆)を持っている場合のみ

  • 使用の構造体。
  • 大きな構造体をメソッドに個別に渡さないでください。構造体のリスト/配列を操作してコピーを避ける
  • 16バイトの制限をハード制限として考慮しないでください。もっと大きな構造体を使用できますが、メソッドに個別に渡すことは避けてください。
+0

これはとても良い説明です。どうも。 – DHN

8

MSDNはこれに良好な点を有する:

✓ タイプのインスタンスが小さく、一般に短命であるか、または一般 他のオブジェクトに埋め込まれている場合代わりにクラスの構造体を定義することを検討してください。

  1. それは論理的にプリミティブ型 (int型、ダブルなど)と同様、単一の値を表し:タイプは 次のすべての特性を持っていない限り、構造体を定義

    Xを避けます。

  2. インスタンスサイズが16バイト未満です。
  3. 不変です。
  4. 頻繁にボックスに入れる必要はありません。

また、MSDNは、私は、クラスを超える構造体の最大化利用を中心にアプリケーションを設計する必要があり

Struct Designを持っていますか?

これは実装しようとしている内容によって異なります。構造体は、実装しようとしている小さな構造体があり、値のように動作するときに使用されます。つまり、クラスを介してstructを使用することは、理想的なステートメントまたはアプローチではありません。

2

まあ、短い答えは「あなたはできますが、そうすべきではありません」です。

クラスと構造の主な違いは、構造体がValue型を定義し、クラスが参照型を定義することです。したがって、実際には、プログラムの動作が上記の違いによって大きく影響される可能性があるため、単に「クラス」ワードを「構造体」に置き換えて関数を移動することはできません。次に、新しいアプリケーションを最初から設計する場合は、適切な構造またはクラスを使用して論理オブジェクトを定義するかどうかを検討できますが、コードではそのことを念頭に置く必要があります。 私はこれが助けてくれることを願っています!

0

構造体をクラスに変換しても、アプリケーションのパフォーマンスは自動的に向上しません。
どのように使用するか、クラスオブジェクトをどのように使用したかによって異なります。

クラスのオブジェクトをたくさん作成して破棄した場合、そのクラスのオブジェクトを再利用するか、構造体を作成して再利用することもできます
(これもクラスで行うことができます) 。あなたがメソッドを呼び出し、パラメータを送信したり、値を返す


クラスを参照でを渡され、構造体は値を渡されます。
時間を惜しみなく渡すと、パフォーマンスが向上する可能性があります。
(ただし、良いプログラミングでは、メソッドを含むクラスのフィールドとしてデータを作成することで、メソッドに常に渡すのを避けることもできます)。


については、構造体内にメソッドを持たせることもできます。必ずしも静的クラスに移動する必要はありません。

struct SimpleStruct 
{ 
    private int xval; 

    public int X 
    { 
     get 
     { 
      return xval; 
     } 
     set 
     { 
      if (value < 100) xval = value; 
     } 
    } 

    public void DisplayX() 
    { 
     Console.WriteLine("The stored value is: "+xval); 
    } 
} 

https://msdn.microsoft.com/en-us/library/aa288471.aspx

1

struct over classを使用するとどのくらいのパフォーマンスが得られますか?

"可能性があります"と答えた場合は、何倍も速くなる可能性があります。

ただし、何倍も遅くなる場合もあります。

ほとんどの場合、それはどちらにもなりませんが、わずかな利益または損失を与えます。

"これより速くするために構造体を使用します"というのは、それ自体が間違った考え方です。

実際に値タイプでなければならないので、何かがValueTypeであるかどうかを検討することが出発点であれば、使用され、推論されているか、そのような価値タイプではないのでValueTypeであってはなりません。そうすれば、その特定のケースに対して最も優れた選択肢が得られる可能性があります。95%それ以上の時間が必要です。

残りの5%のうち、おそらく90%は、あなたが他の方法をとってしまった場合には、パフォーマンスがあまり低下しません。 (あるメソッドで20ミリ秒を節約すると、そのメソッドが100万回呼び出された場合、実行時間は5時間半節約されましたが、20ミリ秒を保存した後に呼び出されると、気付かないことさえあります)。

パフォーマンス上の理由から実際に値型と参照型の間で変更したい場合は、別の方法ではなくstructclassになることがよくあります。確かに値の型が16バイトをはるかに超えてしまうことを避けることは、値や参照型であることを意味する固有の部分ではなく、パフォーマンスの最適化ではありますが、引用されたガイドラインです。

また、コードを呼び出すことによって値型と参照型の違いに注目することも重要です。変更可能な参照型の配列(または他のコレクション)よりも、変更可能な構造体の配列ではるかに高速な操作がいくつかあります。しかし、それらを利用するには、フィールドを公開し、値型を変更可能にする必要があります。どちらもかなりの困難を引き起こす可能性があります。このような最適化は、それらを使用するクラス内でprivateタイプの場合は妥当で、internalタイプの場合はプッシュしますが、publicタイプを使用すると問題が発生します。