C#のソフトリアルタイムコードに対してどのような最適化を行うことができますか?


8

C#でソフトリアルタイムアプリケーションを作成しています。ネットワークからのハードウェア要求への応答などの特定のタスクは、特定のミリ秒以内に完了する必要があります。ただし、そうすることは100%ミッションクリティカルではありません(つまり、ほとんどの時間に時間どおりにあることを許容でき、1%は望ましくありませんが失敗ではありません)。したがって、「ソフト」な部分です。

C#はマネージ言語であり、マネージ言語はリアルタイムアプリケーションには特に適していません。ただし、C#で物事を成し遂げることができる速度、およびリフレクションやメモリ管理などの言語機能により、このアプリケーションを構築するタスクがはるかに簡単になります。

オーバーヘッドの量を減らして確定性を高めるために実行できる最適化または設計戦略はありますか?理想的には私は次の目標を持っているでしょう

  • 「安全」になるまでガベージコレクションを遅らせる
  • ガベージコレクターがリアルタイムプロセスに干渉することなく動作できるようにする
  • さまざまなタスクのスレッド/プロセスの優先順位

C#でこれらを行う方法はありますか、C#を使用するときにリアルタイムに関して他に注意する点はありますか?

アプリケーションのプラットフォームターゲットは、Windows 7 64ビットの.NET 4.0クライアントプロファイルです。現在はクライアントプロファイルに設定していますが、これはデフォルトのオプションであり、特別な理由で選択されませんでした。


2
この記事はあなたを助けるかもしれません。これはビデオゲーム開発者を対象としていますが、これは一種のソフトリアルタイムアプリケーションでもあります。ただし、記事も少し古く、GCの仕組みの背後にある基本原則は大きく変わったとは思いませんが、それがまだ最新であることを再確認することをお勧めします。
Doval 2014

C#について言及しているが、ターゲットプラットフォームやランタイムについては言及していない(例:PC / Unity + Mono / Mono上の.NETなど)-詳細をもう少し教えてもらえますか?
Jトラナ2014

@JTrana詳細を編集しました
9a3eedi

1)実際に問題に気づきましたか?バックグラウンドGCのおかげで、GCの特定の部分でスレッドが短時間だけ停止するはずですが、他の多くの部分は干渉なしに並行して実行できます。2)ここで何ミリ秒話しているのですか?
CodesInChaos 2014

2
@Doval Xboxで実行されているXNAによって使用されるコンパクトフレームワークのGCは、通常のフレームワークで使用されるGCよりもはるかに悪いです。レイテンシに役立つバックグラウンドコレクションに関連する.net 4.0のGCに大きな変更がありました。バックグラウンドコレクションを使用すると、アプリケーションの動作中に、高価なGen2コレクションをバックグラウンドで実行できます。Gen2コレクションが進行中にGen0 / Gen1コレクションを実行することもできます。
CodesInChaos 2014

回答:


7

最初の2つの箇条書きを満たす最適化は、オブジェクトプールと呼ばれます。それは

  1. プログラムの開始時にオブジェクトのプールを作成し、
  2. それらのオブジェクトへの参照をリストに維持して、ガベージコレクションが行われないようにします。
  3. 必要に応じてプールからプログラムにオブジェクトを渡す
  4. オブジェクトの使用が終わったら、オブジェクトをプールに戻します。

ConcurrentBag hereを使用して、オブジェクトプールを実装するクラスの例を見つけることができます。

スレッド/プロセスの優先順位は、実行時に簡単に設定できます。スレッドクラスは、あなたが優先度とプロセッサ親和性を設定することができるようにするメソッドとプロパティを持っています。プロセスクラスは、同様の施設が含まれています。


3
これは、「後で最適化する」のように、アプリケーションが完了して動作した後に行う必要があるように見えます。それにもかかわらず、決定論を高める方法として私には理にかなっています。
9a3eedi 2014

1
私が行う提案は、「早期に最適化する」でしょうか。
ロバートハーベイ

2
ガベージコレクターには、いくつかの貴重な構成オプションがあります。一般的に、その動作はプログラムの大部分で最適であると想定されています。Windowsオペレーティングシステムも.NET Frameworkもハードリアルタイム環境での使用を意図したものではないことに注意してください。はい、私はあなたがソフトリアルタイムと言ったのを知っていますが、それでも。
Robert Harvey

2
@ 9a3eedi:アプリケーション開発後にオブジェクトプールを追加できるかどうかについて、次のアドバイスを提供できます。(1)プールしたいすべてのオブジェクトにオブジェクトファクトリ(オブジェクトプールを兼ねる)を注入する必要があります。(2)すべてのコンストラクタメソッドをファクトリメソッドで置き換えます。(3)各オブジェクトにはリサイクルメソッドがあります。自分自身をプールファクトリーに戻し(4)オブジェクトをリサイクル可能に実装します。ワイプされてから、新しい情報で書き直されます。APIインターフェースを事前に設計する必要がある場合は、これを考慮に入れることができます。
rwong 2014

3
私の経験では、オブジェクトプールは大きな配列(バッファーなど)のリサイクルに役立ちます。小さなオブジェクトの場合、ランタイムは手動のプールなしでうまく機能する傾向があります。
CodesInChaos 2014


2

管理された環境でゲーム開発が行うのと同じアプローチを取り、オブジェクトの作成/死を最小限に抑えるようにしてください。

たとえば、開始時に必要になる可能性が高いすべてのオブジェクトを作成し、強引にプールし、可能な限り参照を渡し、短期的な中間オブジェクトを作成する操作を回避する


一部のクラスを(不変の)構造体に変更すると、短期的な中間オブジェクトの作成を回避できますか?
9a3eedi 2014

通常、構造体とクラスのどちらを選択しても、「オブジェクト」の寿命に大きな影響はありません(ただし、構造体には、値型の「シングルトン」スタイルのロジックが組み込まれている場合を除きます)。不変であることが役立つ場合がありますが、それは実際にはケースバイケースで決まります。
lzcd 2014

1
@ 9a3eedi:不変オブジェクトを使用するということは、実際に何かを「変更」する必要がある場合は常に、変更された値で新しいオブジェクトを作成する必要があることを意味します(おそらく新しいオブジェクトと引き換えに古いオブジェクトを破棄します)。これは、GCのために大量のメモリをクリーンアップする必要があるため、希望とは正反対です。
Doc Brown

@DocBrown +1。ただし、GCは有効期間が短いオブジェクト用に調整されています。コレクションが発生したときに死んでいるオブジェクトに料金を支払う必要はありません(ただし、crazyのように割り当てると、コレクションの頻度が高くなります)。あなたは間違っていないですが、それは問題が手動メモリ管理と敗北にマネージコードの半分の目的は金額をプールするので、最初の場所でありますことを確認する価値がある(他の半分は未定義の動作を回避している。)
Doval

@DocBrownまた、コンパイラ/ランタイムがスコープをエスケープしないことが証明できるオブジェクトは、ヒープではなくスタックに割り当てられるため、場合によっては、一時オブジェクトがガベージコレクションにまったく影響を与えません。
Doval 2014

0

ターゲット環境(Windows)はプリエンプティブなマルチタスクO / Sであることを覚えておいてください。言い換えると、ソフトリアルタイムプロセスはいつか別の時点で必ず横取りされ、.NETガベージコレクション以外のレイテンシが発生します。タイムスライス(量子)の値を減らし(デフォルトは16ミリ秒など)、プロセスの優先度を上げることで軽減できます(ただし、実際的な制限はあります)が、他の重要なプロセスがまだ必要であるため、横取りが発生する/発生します。何かをする。これはすべてプログラミング言語とは関係ありません。O / Sの基本です。

GCの問題は別として、標準のWindowsマシンで実行されているアプリケーションは、おそらく数ミリ秒のレイテンシを提供できます。それは100%の確率で保証されるものではありません。チューニング(短いクォンタム、高い優先度)を使用しても、時折高い待機時間が発生します。それは獣の性質です。

結論:特に数ミリ秒程度の応答時間を保証する必要がある場合、Windowsはおそらく配信O / Sに最適ではありません。


同意する。私はあちこちで数ミリ秒の遅延を受け入れることをいとわないので、「ソフトリアルタイム」の部分ですが、理想的にはできるだけ最小限に抑えたいです。おそらく、
将来的に
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.