2016-01-29 5 views
6

私はImproving .NET Application Performance and Scalabilityを読んでいました。 が繰り返しフィールドまたはプロパティアクセスを避けるというタイトルのセクションでは、ガイドラインが含まれていますループの間静的なままであるプロパティのコンパイラの最適化

あなたがループの期間中に静的なデータを使用している場合は、代わりに繰り返しフィールドまたはプロパティにアクセスするループの前にそれ を得ます。

次のコードは、この例のように与えられる:

for (int item = 0; item < Customer.Orders.Count; item++) 
{ 
    CalculateTax(Customer.State, Customer.Zip, Customer.Orders[item]); 
} 

string state = Customer.State; 
string zip = Customer.Zip; 
int count = Customers.Orders.Count; 
for (int item = 0; item < count; item++) 
{ 
    CalculateTax(state, zip, Customer.Orders[item]); 
} 

物品状態になる:これらのフィールドである場合、その

注意、それはコンパイラのために可能性があります この最適化を行う自動lly。それらがプロパティの場合は、多くは です。プロパティが仮想の場合は、自動的に を実行することはできません。

この方法でコンパイラによってプロパティを最適化するのはなぜですか?なぜ特定のプロパティを最適化するかどうかをいつ期待できますか?アクセサーで追加の操作が実行されるプロパティはコンパイラが最適化するのが難しく、バッキングフィールドのみを変更するものは最適化される可能性が高いと思いますが、いくつかのより具体的なルールが必要です。自動実装されたプロパティは常に最適化されていますか?

答えて

3

を考えることは最適化を適用するジッタを必要とします。ゲッターが小さく、例外をスローしないときに動作する傾向があります。これは、オプティマイザがゲッターが他のコードの影響を受ける可能性のある状態に依存していないことを確かめるために必要です。

たとえば、Customer.Orders []インデクサーがCustomer.Stateプロパティを変更すると、手で最適化されたコードがどのように間違っているか注意してください。このようなレイジーコードは当然ですが、これは決して行われていないようなものではありません:)オプティマイザは確実です。

第2に、フィールドアクセスコードをループ本体から持ち上げる必要があります。 "不変なコードの動き"と呼ばれる最適化。ループボディー内のステートメントが値に影響しないことをジッターが証明できる場合は、単純なプロパティゲッターコードで動作します。

ジッタオプティマイザはそれを実装しますが、それは恒星ではありません。この特定のケースでは、CalculateTax()メソッドをインライン化できないときには、あきらめてしまう可能性が非常に高いです。ネイティブコンパイラは、これをより積極的に最適化し、メモリとその解析時間を消費する余裕があります。ジッタ・オプティマイザは、一時停止を避けるために非常に厳しい期限を過ぎていなければなりません。

これを自分で行うときは、オプティマイザの制約を守ってください。もちろん、これらの方法がの場合は、にはあなたが頼りにしなかった副作用があります。 プロファイラからこのコードが実際に実行時間に影響を与えるコードの典型的な10%のホット・パスにあることがわかったときにこれを実行します。ここでは低い確率で、顧客/注文データを取得するためのdbaseクエリは税計算よりも高価です。幸いなことに、このようなコード変換は、コードを読みやすくして、通常は無料で入手する傾向があります。 YMMV。

ジッタ最適化のバックグラウンドis here

4

このようにコンパイラによってプロパティが最適化されるのはなぜですか?なぜ特定のプロパティを最適化するかどうかをいつ期待できますか?

プロパティは必ずしもフィールドのラッパーではありません。プロパティにある程度のロジックがある場合、ループが開始されたときに最初に取得した値を再利用するのが正しいことをコンパイラが証明することははるかに困難になります。

まずそれがフィールドアクセスの同等に変わるように、プロパティのゲッターメソッドがインライン化される必要があります。極端な例として

private Random rnd = new Random(); 
public int MyProperty 
{ 
    get { return rnd.Next(); } 
} 
+0

また、バッキングフィールドの値を返すだけであっても、コンパイラーはバッキングフィールドがループ全体で変更できないことを証明する必要があります。これは、難しい(しばしば不可能な)ことですほとんどの場合。 – Servy

+0

@Servy:そうですが、これはフィールドと同じ場合、コンパイラがこの最適化を自動的に行うことが可能であることに注意してください。 –

+0

コンパイラが* only *プロパティを返すことが証明できる場合フィールドの値、* then *同じ値。それは、プロパティがそれを行うかどうかを知っているかもしれません。 @EricJ。 – Servy

関連する問題