4

背景: リクエスタにオブジェクトを提供することを目的とするサービスがあります。基本的には、データベースから複雑なデータを取得し、それを 1 回変換して (データのビューに少し似ています)、単純化されたレコードを生成します。次に、要求に応じて最大 10 万件のレコード (要求の性質による) を提供することで、他のサービスからの要求を処理します。

アイデアは、複雑な変換が一度行われ、サービスによってキャッシュされるということです-ビューがアクセスされるたびにデータベースにそれを処理させるよりも速く機能し、私の目的ではうまく機能します. (一部の人はこれを SSOS と呼んでいると思います)

データがキャッシュされる方法は、標準の .Net 型のプロパティ バッグであるオブジェクトのリストにあります。これらのオブジェクトには、他のオブジェクトへの参照はありません。レコードは定期的に変更され、キャッシュを更新する必要があります。つまり、元のレコードを見つけて破棄し、置き換える必要があります。

これで、キャッシュ内のレコードは長い間存在し、Gen 2 コレクションとしてマークされます。これらのオブジェクトは長い間 (意図的に) ぶらぶらしているため、ほぼすべてのコレクションが Gen2 フェーズで発生します。

したがって、Gen2 コレクションは遅いというのが私の理解です。コレクションが主に Gen2 で動作している場合、オプティマイザーはこれをより頻繁に実行します。

完全なGen2コレクションをトリガーしない方法で、リスト内のオブジェクトを逆参照できるようにしたいと思います... Gen0としてマークしてから逆参照する方法があるのではないかと考えていました置き換える前に参照しますが、それは不可能だと思います。

私はこれに.Net 4を使用することに制約されており、アプリケーションは、完全なリストまたは一定期間にわたるリストへの変更を要求する最大100のクライアントにデータを提供するサービスです。

質問: GC に適した方法で長寿命のオブジェクトを逆参照する方法、またはこの問題に対処する別の方法を提案できる人はいますか?

4

1 に答える 1

8

これに対する簡単な答えはありません。ここで説明したように、存続期間の長いオブジェクトが多数ある場合、完全なコレクションは実際に害を及ぼす可能性があります。絵は千の言葉を語るので:

ここに画像の説明を入力

これらの垂直スパイクは、ガベージ コレクションが発生する場所であり、応答時間を大幅に短縮します。

この影響を軽減する方法は、膨大な数の寿命の長いオブジェクトを持たないようにすることでした。私たちが行ったことは、クラスをstructs に変更することでした。これは、唯一のオブジェクトがそれらを含む配列であることを意味しました。ここで幸運だったのは、データが単純でstring、もちろんそれ自体がオブジェクトである s を含まなかったことです。また、以前はコレクションだったものを減らすために、クレイジーな固定サイズのバッファー作業を行い、インデックスへの参照(配列への参照) を変更しました。データを使用する必要がある場合は、おそらく、同じ値を持つ 20,000 の異なるインスタンスがないことを確認してください。ある種の手動インターナー (astring stringDictionary<string,string>で十分です)は、そこで非常に役立ちます。

ストレージから古いデータをいつでも作成できるため、これはパブリックAPI に影響を与える必要がないことに注意してください。違いは、これは DTO として一時的にしか存在しないことです。そのため、次の gen-0 スイープで安価に収集されます。classstructclass

YMMV ですが、これで十分に機能しました。

問題は、 sを扱うときは十分に注意する必要があることです。structそれらを不変にすることを強くお勧めします。

于 2013-03-08T12:54:04.460 に答える