最近Util
、友人が作成したクラスに非常に多くのinline
メソッドがあるのを見ました。クラスは画像に関するもので、次のようなメソッドがあります
public static inline function resize ( img:Image, width:Int, height:Int)
{
//... method implementation goes here.
}
を使用する理由を彼に尋ねましたinline
。コンパイラが変更されることを知っています
var img:Image = ImgUtil.resize(img, 100, 100);
に
var img:Image = // Implementation of method here
彼は単に、関数の呼び出しを減らし、それらをユーティリティ メソッドでのみ使用すると述べました。毎回同じコードをコピーすると、プログラムのサイズが大きくなりませんか?
これは今日必要ですか?必要な場合、いつ使用する必要がありますか?
編集
リンクをたどりたくない将来の視聴者を助けるために、パトリックが提供したリンクにあるリストに、最も多くの問題と利点をリストしています.
問題
呼び出しサイトを展開された関数本体に置き換えると、いくつかの点でパフォーマンスが低下する可能性があります。
- 多くの組み込みシステムなど、速度よりもコード サイズが重要なアプリケーションでは、単純なミューテーター メソッドなどの非常に小さな関数を除いて、インライン化は通常不利です。
- コード サイズの増加により、コードの小さな重要なセクションがキャッシュに収まらなくなり、キャッシュ ミスやスローダウンが発生する可能性があります。
- インライン化されたプロシージャから追加された変数は、追加のレジスタを消費する可能性があり、レジスタのプレッシャーがすでに高い領域では、これによりスピルが強制され、追加の RAM アクセスが発生する可能性があります。
- 言語仕様により、プログラムは、プロシージャーがインライン化された後は作成できなくなる、プロシージャーへの引数に関する追加の仮定を作成できる場合があります。
- コードサイズを大きくしすぎると、RAM サイズなどのリソースの制約を超えて、プログラムが実行できなくなったり、スラッシングが発生したりする可能性があります。現在、これは非常に積極的なインライン化を除いて、デスクトップまたはサーバー コンピューターで問題になることはほとんどありませんが、組み込みシステムでは依然として問題になる可能性があります。
通常、コンパイラ開発者はこれらの問題を念頭に置いており、ほとんどの場合、パフォーマンスを悪化させるのではなく、パフォーマンスを向上させるためにインライン化する関数を選択するヒューリスティックをコンパイラに組み込みます。
利点:
インライン展開自体は、呼び出しのオーバーヘッドを排除するための最適化ですが、有効な変換としてははるかに重要です。つまり、コンパイラが呼び出しサイトのコンテキストで関数本体を展開すると (多くの場合、固定定数である可能性のある引数を使用して)、以前は不可能だったさまざまな変換を行うことができる場合があります。たとえば、条件分岐は、この特定の呼び出しサイトで常に true または常に false であることが判明する場合があります。これにより、デッド コードの削除、ループ不変コードの移動、誘導変数の削除が可能になります。