何度も私は、オブジェクトの割り当てが高価であるという魅力を思いついた。参照型のメモリとCLRの値型のコストの比較は何ですか?
ほとんどの参照はどちらかである:彼らは、説明が
- 斜め、または
- が、その中で不完全であるように、具体的何コストがあり、それは何と比較する方法対象ではありませんということ参照が文脈的であり、それが議論している主題を取り上げようとしているか、または完全に不正確であるためです。
- または、オブジェクトのメモリ割り当てのコストを比較していることを意味するものではありません。オブジェクトを作成するのは高価ですが、に対しては何ですか?なぜ?そしてどうやって?それと、いくらですか?
私は過去に出会ったすべての参考文献を見つけることができませんが、この質問をするために突然発生した1つの動機が私のモチベーション(および付随する欲求不満)につながりました。それは、信頼できるソースではなく、ここで、それが行く:
例1
This articlestructs
に書かれています:構造体で
あなたがC#言語でオブジェクトのオーバーヘッドを避けます。 は、複数のフィールドを組み合わせることができます。これにより、メモリの負荷が軽減されます。そしてそれは (ときどき)パフォーマンスを向上させます。
今、私はアイデアがありませんこれは何を話しているのですか?確かに、CLRの最も単純なオブジェクトでさえも、次のように12バイトを占めます。
- 4バイトは忘れてしまいました。
- オブジェクトのメソッドテーブルへのポインタの4バイト。
- オブジェクトにフィールドまたはプロパティが含まれていない場合でも、オブジェクトに含まれる最初のフィールドの4バイト。
struct
と値の種類が異なるのですか?確かに、struct
にはメソッドテーブルとヘッダーも必要です。そして、オブジェクトに対して、struct
を宣言することの比較コストはどれくらいですか?それとも、オブジェクトをのいずれかの値の型のと宣言することと比較して、コストを比較するのはどうですか?
例2
根底にある動機は、新しいオブジェクトを作成するためのメモリの割り当てを回避するためである別の例を考えます。
以下の例では、オブジェクトのすべてのコンテンツが消去されて新しいコンテンツの場所が作成されたとしても、コードは新しいキャッシュを作成しないようにStringBuilder
をキャッシュします。新しいオブジェクトの作成だけです。回避される新しいオブジェクトのためのメモリの割り当て。 source of KeyValuePair<TKey, TValue>
から
:コードの最初の行はStringBuilderCache.Acquire
呼び出し
public override string ToString()
{
StringBuilder sb = StringBuilderCache.Acquire(0x10);
sb.Append('[');
if (this.Key != null)
{
sb.Append(this.Key.ToString());
}
sb.Append(", ");
if (this.Value != null)
{
sb.Append(this.Value.ToString());
}
sb.Append(']');
return StringBuilderCache.GetStringAndRelease(sb);
}
注意。以下はthe code for the StringBuilderCache
classです。その目的は、オブジェクトを再作成しないようにStringBuilder
オブジェクトのインスタンスをキャッシュすることです。
internal static class StringBuilderCache
{
// Fields
[ThreadStatic]
private static StringBuilder CachedInstance;
private const int MAX_BUILDER_SIZE = 360;
// Methods
public static StringBuilder Acquire(int capacity = 0x10);
public static string GetStringAndRelease(StringBuilder sb);
public static void Release(StringBuilder sb);
}
そして、以下はこのクラスのsource of the Acquire
methodです。インスタンスが以前に使用可能だった場合、その内容を空にした後に、キャッシュされたインスタンスStringBuilder
を返します。
public static StringBuilder Acquire(int capacity = 0x10)
{
if (capacity <= 360)
{
StringBuilder cachedInstance = CachedInstance;
if ((cachedInstance != null) && (capacity <= cachedInstance.Capacity))
{
CachedInstance = null;
cachedInstance.Clear();
return cachedInstance;
}
}
return new StringBuilder(capacity);
}
例3
私は上記をほのめかし信頼できるソースを発見したと述べました。
次のようにほとんどの記事の冒頭で、MSDN上のC#プログラミングガイドからUsing Structsページは、状態:
で
class
としてポイントを表現するために同じように便利ですが自動的に実装されたプロパティーの場合、struct
がいくつかのシナリオではより効率的になる可能性があります。たとえば、1000 Pointオブジェクトの配列を宣言すると、 は各オブジェクトを参照するために追加のメモリを割り当てます。 このケースでは、struct
は安くなります。
このように、新しいオブジェクトを作成するのは何ですか?
https://stackoverflow.com/questions/203695/does-using-new-on-a-struct-allocate-it-on-the-heap-or-stackおよびhttps://stackoverflow.com/を参照してください。質問/ 79923/what-and-where-are-the-stack-and-heap。 – Polyfun
ええと、オブジェクトを割り当てることは高価ではありません。割り当てがボトルネックになっている場合、C#プログラムはC++プログラムを手際よく打ち負かします。より高価なものにアクセスしています。値の型は、プロセッサがメモリを使用することを好む方法と高度に互換性があり、プロセッサのレジスタに値を格納できるため、perfに非常に大きな違いがあります。ストレージにスタックを使用することは、いつも暑いので便利です。参照型のオブジェクトは、ポインタを介して余分な間接を必要とし、オブジェクトが低速RAMから掘り出される必要があるときにプロセッサが停止する可能性があります。 –
@HansPassantあなたが言っていることは、この答えを考えるとかなり意味があります。 (https://stackoverflow.com/a/45276657/303685)この人は単に 'struct'や' class'インスタンスにアクセスし、その作成コストを除外したパフォーマンステストを行い、アクセス時間の違いも指摘しました。 –