マネージド言語がオブジェクトを手動で削除する機能を提供しないのはなぜですか?
-
18-09-2019 - |
質問
大規模なデータセットを処理する高性能方法を作成するとします。開発者は、CまたはC ++に移動することを余儀なくされるのではなく、手動メモリ管理をオンにすることができないのはなぜですか?
void Process()
{
unmanaged
{
Byte[] buffer;
while (true)
{
buffer = new Byte[1024000000];
// process
delete buffer;
}
}
}
解決
メモリブロックを手動で削除できるようにすることができるようにすることができますが(ランタイムにはGCサイクルを行わずには、ぶら下がっているポインターが生成されることを知る方法がありません)、したがって壊れます。 メモリの安全. 。 GC言語は通常、設計によりメモリセーフです。
とはいえ、特にC#では、あなたはすでに望むことをすることができます:
void Process()
{
unsafe
{
byte* buffer;
while (true)
{
buffer = Marshal.AllocHGlobal(1024000000);
// process
Marshal.FreeHGlobal(buffer);
}
}
}
C/C ++のように、C#の生のポインタータイプの完全なポインター算術があることに注意してください。 buffer[i]
また buffer+i
有効な式です。
他のヒント
高性能で詳細な制御が必要な場合は、CまたはC ++でやっていることを書く必要があります。すべての言語がすべてのものに適しているわけではありません。
追加するために編集:単一の言語はすべてのものに適していません。すべての優れたプログラミング言語ですべての有用な機能を合計すると、矛盾を避けても、C ++よりもはるかに悪い、本当に大きな混乱を招くでしょう。
機能は無料ではありません。言語に機能がある場合、人々はそれを使用する可能性があります。新しいC#マニュアルメモリ管理ルーチンを学習せずに、C#を十分に学習することはできません。コンパイラチームは、便利な他のコンパイラ機能を犠牲にして実装します。この言語は、CやC ++のように解析するのが難しくなる可能性が高く、それがゆっくりとコンピレーションにつながります。 (C ++の男として、C#プロジェクトの1つをコンパイルするとき、私はいつも驚いています。コンピレーションはほとんど瞬時に見えます。)
特徴は、時には予想外の方法で、互いに競合することを特徴とします。 C90は、Cポインターがエイリアスされる可能性がいくつかの最適化を防ぐため、Matrix計算でFortranと同様に行うこともできません。言語でポインター算術を許可する場合、その結果を受け入れる必要があります。
マニュアルメモリ管理を可能にするためのC#拡張機能を提案し、いくつかのケースで役立つでしょう。それは、メモリを別々の方法で割り当てる必要があることを意味し、自動的に管理されたメモリから手動で管理されたメモリを伝える方法が必要です。突然、メモリ管理が複雑になり、プログラマーが台無しにする可能性が高くなり、メモリマネージャー自体がより複雑になります。すべての場合において、より多くの合併症とメモリ管理が遅いことと引き換えに、いくつかのケースで重要なパフォーマンスを少し得ています。
スクリプトから数の計算まで、ほとんどすべての目的に適したプログラミング言語がある場合がありますが、その近くにある人気はありません。それまでの間、私たちは、1つの言語のみを使用することの制限、またはそれらを数回学習してそれらを切り替えるという課題を喜んで受け入れなければなりません。
投稿した例では、バッファを消去して再利用してみませんか?
.NETガベージコレクターは、どのオブジェクトが参照されなくなり、関連するメモリをタイムリーに解放するのに非常に優れています。実際、ゴミコレクターには、このような大きなオブジェクトを置く特別なヒープ(大きなオブジェクトヒープ)があり、それらに対処するように最適化されています。
これに加えて、参照を明示的に解放することを許可しないと、メモリリークとぶら下がったポインターを備えたバグ全体を削除するだけで、はるかに安全なコードにつながります。
GCはコピースキームを使用して生きたままのブロックの数に直線的な時間を費やす可能性があるため(または、コピースキームを使用する可能性があるため、明示的なメモリ管理を備えた言語で行われた各未使用のブロックを個別に解放することは、それをさせるよりも高価になる可能性があります(または各死んだブロックを処理する代わりに、最近のブロックの数)。
ほとんどのカーネルと同じ理由で、独自のスレッドをスケジュールすることができません。あなたが本当に必要ではない時間の99.99+%であり、その機能を公開することは、残りの時間を暴露することはあなたが潜在的に愚かな/危険なことをするように誘惑するだけだからです。
細かい穀物メモリコントロールが本当に必要な場合は、コードのセクションを他のものに書き込みます。