動的コード生成を使用してパフォーマンスを向上させる方法については考えていますが、この問題に取り組む最善の方法はどれかわかりません。
クラスがあるとします
class Calculator
{
int Value1;
int Value2;
//..........
int ValueN;
void DoCalc()
{
if (Value1 > 0)
{
DoValue1RelatedStuff();
}
if (Value2 > 0)
{
DoValue2RelatedStuff();
}
//....
//....
//....
if (ValueN > 0)
{
DoValueNRelatedStuff();
}
}
}
DoCalc メソッドは最下位レベルにあり、計算中に何度も呼び出されます。もう 1 つの重要な側面は、ValueN が最初に設定されるだけで、計算中に変更されないことです。ValueN の多くが 0 であるため、DoCalc メソッドの if の多くは不要です。そのため、動的コード生成がパフォーマンスの向上に役立つことを期待していました。
たとえば、メソッドを作成した場合
void DoCalc_Specific()
{
const Value1 = 0;
const Value2 = 0;
const ValueN = 1;
if (Value1 > 0)
{
DoValue1RelatedStuff();
}
if (Value2 > 0)
{
DoValue2RelatedStuff();
}
....
....
....
if (ValueN > 0)
{
DoValueNRelatedStuff();
}
}
C#コンパイラは、必要なものだけを保持するのに十分スマートです。したがって、ValueN の値に基づいて実行時にそのようなメソッドを作成し、計算中に生成されたメソッドを使用したいと思います。
式木を使えばいいのかなと思いますが、式木は単純なラムダ関数でしか動かないので、関数本体の中でifやwhileなどは使えません。したがって、この場合、このメソッドを適切な方法で変更する必要があります。
もう 1 つの可能性は、必要なコードを文字列として作成し、動的にコンパイルすることです。しかし、既存の方法を使用してそれに応じて変更できれば、私にとってははるかに良いでしょう.
Reflection.Emit もありますが、維持するのが非常に難しいため、これに固執したくありません。
ところで。私は C# に限定されません。したがって、この種の問題に最適なプログラミング言語の提案を歓迎します。いくつかの理由から、LISP を除きます。
1 つの重要な説明。DoValue1RelatedStuff() は、私のアルゴリズムではメソッド呼び出しではありません。これは数式ベースの計算であり、非常に高速です。こう書くべきだった
if (Value1 > 0)
{
// Do Value1 Related Stuff
}
いくつかのパフォーマンス テストを実行したところ、1 つが無効になっている場合に 2 つの if を使用すると、最適化された方法が冗長な if を使用した場合よりも約 2 倍高速であることがわかります。
テストに使用したコードは次のとおりです。
public class Program
{
static void Main(string[] args)
{
int x = 0, y = 2;
var if_st = DateTime.Now.Ticks;
for (var i = 0; i < 10000000; i++)
{
WithIf(x, y);
}
var if_et = DateTime.Now.Ticks - if_st;
Console.WriteLine(if_et.ToString());
var noif_st = DateTime.Now.Ticks;
for (var i = 0; i < 10000000; i++)
{
Without(x, y);
}
var noif_et = DateTime.Now.Ticks - noif_st;
Console.WriteLine(noif_et.ToString());
Console.ReadLine();
}
static double WithIf(int x, int y)
{
var result = 0.0;
for (var i = 0; i < 100; i++)
{
if (x > 0)
{
result += x * 0.01;
}
if (y > 0)
{
result += y * 0.01;
}
}
return result;
}
static double Without(int x, int y)
{
var result = 0.0;
for (var i = 0; i < 100; i++)
{
result += y * 0.01;
}
return result;
}
}