0

次のコード スニペットのうち、発生するオーバーヘッドが最も少ないのはどれですか (または IL は同じですか)? 私のプログラムは、フィードする制約式の数によっては、巨大なギザギザの配列を生成する可能性があります。decimal[][] オブジェクトへのメモリの不要な割り当てを制限したい:

decimal[][] originalFormTableau = CreateOriginalFormTableau();
decimal[][] standardFormTableau = InsertSlackVariables(originalFormTableau);
this.Engine = new SimplexEngine(standardFormTableau, normalizationThreshold);

また

this.Engine = new SimplexEngine(
    InsertSlackVariables(
    CreateOriginalFormTableau()),
    normalizationThreshold);

またはその他の提案(代わりに ref を使用する可能性がありますか?)

4

2 に答える 2

4

それらを分解してください:

//we start with a space on the stack from a local or parameter
//holding whatever normalizationThreshold is
//1. Create a space on the stack to hold a decimal[][]
//Call CreateOriginalFormTableau() method
//assign result to that space.
decimal[][] originalFormTableau = CreateOriginalFormTableau();
//2. Create a space on the stack to hold a decimal[][]
//Call InsertSlackVariables() method, passing in the first decimal[][]
//assign result to that second space.
decimal[][] standardFormTableau = InsertSlackVariables(originalFormTableau);
//3. Call the Engine setter with the second space or assign it to the Engine field.
this.Engine = new SimplexEngine(standardFormTableau, normalizationThreshold)

VS:

//we start with a space on the stack from a local or parameter
//holding whatever normalizationThreshold is
//1. Create a space on the stack to hold a decimal[][]
//Call CreateOriginalFormTableau() method
//assign result to that space.
//2. Create a space on the stack to hold a decimal[][]
//Call InsertSlackVariables() method, passing in the first decimal[][]
//assign result to that second space.
//3. Call the Engine setter with the second space or assign it to the Engine field.
this.Engine = new SimplexEngine(
  InsertSlackVariables(
  CreateOriginalFormTableau()),
  normalizationThreshold);

それらはまったく同じコードですが、あるバージョンでは名前が付けられていないものに名前が付けられています。

デバッグ ビルドではパフォーマンスがわずかに異なる可能性がありますが、それでも疑問があります (リリース ビルドではスタック スロットが再利用され、デバッグ ビルドでは再利用されない場合があるため、勝った後でもスコープ内の変数を調べることができます)。再び使用されることはありませんが、名前のないスロットも再利用されない可能性が高く、たとえそれが違いを生んだとしても、影響はわずかです)。

于 2012-09-05T09:53:06.000 に答える
3

Did the test, for science:

Version 1

public void Test1()
{
    decimal[][] originalFormTableau = CreateOriginalFormTableau();
    decimal[][] standardFormTableau = InsertSlackVariables(originalFormTableau);
    this.Engine = new SimplexEngine(standardFormTableau, normalizationThreshold);
}

Outputs:

.method public hidebysig instance void Test1() cil managed
{
    .maxstack 4
    .locals init (
        [0] valuetype [mscorlib]System.Decimal[][] originalFormTableau,
        [1] valuetype [mscorlib]System.Decimal[][] standardFormTableau)
    L_0000: ldarg.0 
    L_0001: call instance valuetype [mscorlib]System.Decimal[][] ConsoleApplication2.Class2::CreateOriginalFormTableau()
    L_0006: stloc.0 
    L_0007: ldarg.0 
    L_0008: ldloc.0 
    L_0009: call instance valuetype [mscorlib]System.Decimal[][] ConsoleApplication2.Class2::InsertSlackVariables(valuetype [mscorlib]System.Decimal[][])
    L_000e: stloc.1 
    L_000f: ldarg.0 
    L_0010: ldloc.1 
    L_0011: ldarg.0 
    L_0012: call instance object ConsoleApplication2.Class2::get_normalizationThreshold()
    L_0017: newobj instance void ConsoleApplication2.SimplexEngine::.ctor(valuetype [mscorlib]System.Decimal[][], object)
    L_001c: call instance void ConsoleApplication2.Class2::set_Engine(class ConsoleApplication2.SimplexEngine)
    L_0021: ret 
}

Version 2

this.Engine = new SimplexEngine(
    InsertSlackVariables(
    CreateOriginalFormTableau()),
    normalizationThreshold);

Outputs:

.method public hidebysig instance void Test2() cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: ldarg.0 
    L_0002: ldarg.0 
    L_0003: call instance valuetype [mscorlib]System.Decimal[][] ConsoleApplication2.Class2::CreateOriginalFormTableau()
    L_0008: call instance valuetype [mscorlib]System.Decimal[][] ConsoleApplication2.Class2::InsertSlackVariables(valuetype [mscorlib]System.Decimal[][])
    L_000d: ldarg.0 
    L_000e: call instance object ConsoleApplication2.Class2::get_normalizationThreshold()
    L_0013: newobj instance void ConsoleApplication2.SimplexEngine::.ctor(valuetype [mscorlib]System.Decimal[][], object)
    L_0018: call instance void ConsoleApplication2.Class2::set_Engine(class ConsoleApplication2.SimplexEngine)
    L_001d: ret 
}

Compiled in release, optimizations turned on. I have to say, since the local variables aren't reused in the method, I believed the compiler would rewrite Test1 to look like Test2. Somehow, it didn't. So I guess Test2 would be slightly faster, though it's probably not in a measurable way.

So, unless you're searching for microsecond optimizations, go for the most readable one.

于 2012-09-05T10:02:31.793 に答える