4

最適化する関数がやや大きい(コメントなしで約80行のコード)。

プロファイラーに作業を任せるための一環として、2つのコードチャンクを取得し、それらを別々の関数に配置しました(これは、元に戻すことができるまでの一時的なものであると想定されています)。

興味深い部分はこれです:私のテストケースは29.8秒かかり
ました最初のチャンクを別の関数に入れた後、関数呼び出しのオーバーヘッドによる小さなパフォーマンスの低下が見られました。(30.2秒)コードの2番目のチャンクを別の関数に入れると、24.2秒までかなり大きなパフォーマンスの向上が得られました

コードの2番目のチャンクは、かなり大きなリンクリストへの挿入であり、バイナリツリーなどに置き換える予定ですが、それでもこの20%の改善はかなり混乱します。

tl; dr:コードを最適化しようとすると、コードのブロックを別の関数に入れると、パフォーマンスが20%向上することに気付きました。そんなことがあるものか?

編集:リリースビルドでも実行されていることを確認

4

2 に答える 2

6

このコードブロックを抽出することで、関数が単純になりました。多分それはコンパイラが関数を効率的にコンパイルするのを助けました。ローカル変数が少ないため、レジスターのプレッシャーが軽減された可能性があります。

時々、それは単なる偶然です。コードをランダムに動かすと、パフォーマンスが(両方の方法で)変わる可能性が非常に高くなります。たまたま、悪化ではなく改善にぶつかったのかもしれません。

「ジグリング」がパフォーマンスを変えるのはなぜですか?これにより、アドレスアラインメント、分岐予測、コンパイラがホットなものとコールドなもの、CPU命令キャッシュの使用状況を変更する可能性があります。

これらはすべて、セマンティックの観点からの実装の詳細です。しかし、それらはパフォーマンスに影響を与えます。それらは非常に低いレベルで動作し、非常に複雑であるため、まったく予測できません。

于 2012-04-29T16:56:30.063 に答える
1

コード例がなければ、まともな説明をするのは難しいですが、ほとんどのプログラミング言語の場合、usrの答えは非常に真実です。

ただし、Flashコンパイラに関しては予約があります。経験から、関数呼び出しのオーバーヘッドが非常に高いため、セルフインライン化(​​つまり、これまでとは逆)は、フラッシュ内の関数を最適化するための最良の方法の1つです。

そうは言っても、ローカル変数が少ないことがパフォーマンスの向上が見られる理由である可能性が高いというusrに同意します。Flashにはブロックレベルのスコープがありません。つまり、関数で宣言されたすべての変数には、関数が呼び出されたときにメモリが割り当てられます。コードの2番目のブロックが、その特定のコードブロックでのみ役立つ変数を宣言し、このコードがたまにしか実行されない場合(ifステートメントにある場合)、パフォーマンスの向上を説明できます。

パフォーマンスの向上が見られる場合の例:

public function foo() : void
{
    var bar : MyObj;
    //do stuff with bar

    if(someValuesAreTrue)
    {
        var jad  : oObj;
        var jad2 : oObj;
        //etc
        //do something with jad
    }
}

//changed to 
public function foo() : void
{
    var bar : MyObj;
    //do stuff with bar

    if(someValuesAreTrue)
    {
        subFunc();
    }
}
private function subFunc() : void
{
    var jad  : oObj;
    var jad2 : oObj;
    //etc
    //do something with jad
}

これが現在のタイプの状況ではない場合、自己インライン化に代わる他のパフォーマンスを向上させる代替案へのより良い洞察を提供できるので、いくつかのコードを見るのは非常に興味があります。

于 2012-04-30T10:28:12.107 に答える