我知道如何通过动态代码生成来提高性能,但我不确定哪种方法是解决这个问题的最佳方法。
假设我有一堂课
class Calculator
{
int Value1;
int Value2;
//..........
int ValueN;
void DoCalc()
{
if (Value1 > 0)
{
DoValue1RelatedStuff();
}
if (Value2 > 0)
{
DoValue2RelatedStuff();
}
//....
//....
//....
if (ValueN > 0)
{
DoValueNRelatedStuff();
}
}
}
DoCalc 方法处于最低级别,在计算过程中被多次调用。另一个重要方面是 ValueN 仅在开始时设置,在计算过程中不会更改。DoCalc 方法中的许多 if 是不必要的,因为许多 ValueN 为 0。所以我希望动态代码生成有助于提高性能。
例如,如果我创建一个方法
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 的值创建这样的方法,并在计算期间使用生成的方法。
我想我可以为此使用表达式树,但表达式树仅适用于简单的 lambda 函数,因此我不能在函数体内使用 if、while 等内容。因此,在这种情况下,我需要以适当的方式更改此方法。
另一种可能性是将必要的代码创建为字符串并动态编译它。但如果我能采用现有的方法并相应地修改它,那对我来说会好得多。
还有 Reflection.Emit,但我不想坚持使用它,因为它很难维护。
顺便提一句。我不仅限于 C#。因此,我愿意接受最适合此类问题的编程语言的建议。出于几个原因,除了 LISP。
一项重要的澄清。DoValue1RelatedStuff() 不是我算法中的方法调用。这只是一些基于公式的计算,而且速度非常快。我应该这样写
if (Value1 > 0)
{
// Do Value1 Related Stuff
}
我已经运行了一些性能测试,并且我可以看到,当禁用一个 if 时,使用两个 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;
}
}