执行前预编译C#方法

执行前预编译C#方法,c#,load-testing,C#,Load Testing,我这样测量代码速度: var sw = new Stopwatch(); sw.Start(); DoSomething(); sw.Stop(); AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds); var sw = new Stopwatch(); DoSomething(); sw.Start(); DoSomething(); sw.Stop(); AddLog("Method speed is (ms): "+sw.Ela

我这样测量代码速度:

var sw = new Stopwatch();
sw.Start();
DoSomething();
sw.Stop();
AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds);
var sw = new Stopwatch();
DoSomething();
sw.Start();
DoSomething();
sw.Stop();
AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds);
但是DoSomething()的第一个调用很慢,因为代码正在编译。 解决方法是测量第二次呼叫的速度,如下所示:

var sw = new Stopwatch();
sw.Start();
DoSomething();
sw.Stop();
AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds);
var sw = new Stopwatch();
DoSomething();
sw.Start();
DoSomething();
sw.Stop();
AddLog("Method speed is (ms): "+sw.ElapsedMilliseconds);

有没有办法在不进行第一次调用的情况下预编译DoSomethig()?

您之所以看到时间上的差异,是因为运行时正在编译该方法,以便在第一次调用之前执行,而当它即将被第二次调用时,运行该方法所需的所有内容都已编译。您可以使用来完成此任务。它会在执行之前将il编译为本机exe,从而缩短启动时间

对于您的特定场景,我认为ngen.exe是该作业的正确工具,因为它可以作为生成后事件触发,以便提前编译程序集,并在需要时准备就绪。如果使用PrepareMethod,那么在运行测试时仍然会延迟JIT方法,而不是在实际调用它们时


文件中没有明确说明,但根据 文章(除其他外)您可以使用
RuntimeHelpers.PrepareMethod
预编译方法

为了详细说明我的评论(如上所述),这里有一个代码示例:

static void WarmUp()
{
    var handle = typeof (Program).GetMethod("DoSomething").MethodHandle;
    RuntimeHelpers.PrepareMethod(handle);
}
更新

下面是一个更通用(尽管有些脆弱)的解决方案,它也将考虑实例成员:

public static class MethodWarmerUper
{
    public static void WarmUp(string methodName)
    {
        var handle = FindMethodWithName(methodName).MethodHandle;
        RuntimeHelpers.PrepareMethod(handle);
    }

    private static MethodInfo FindMethodWithName(string methodName)
    {
        return 
            Assembly.GetExecutingAssembly()
                    .GetTypes()
                    .SelectMany(type => type.GetMethods(MethodBindingFlags))
                    .FirstOrDefault(method => method.Name == methodName);
    }

    private const BindingFlags MethodBindingFlags =
        BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic |
        BindingFlags.Instance | BindingFlags.Static;
}

你能告诉我们那是什么吗?在第一次调用中,我没有理解代码编译是什么意思。C#已经编译成IL,所以从技术上讲,C#代码永远不会在运行时编译。Leri是对的:它可以提供一些关于
DoSomething()
功能的信息。还有,我很好奇:你看到第一个版本和第二个版本有多大的不同?看看也许能帮上忙。等等。。。。如果
DoSomething()
可以在测试数据库时改变数据库并通知外部世界,我认为您可能需要在这里重新考虑您的解决方案……文档中并没有明确说明这一点,但根据文章(以及其他文章),您可以使用
RuntimeHelpers.PrepareMethod
来预编译方法。NGen也是一个选项。在我的情况下,这不是最好的方法,因为我的任务是单元测试(TestClass,TestMethod)的一部分。您仍然可以在应用程序的编译后阶段使用NGen.exe预编译测试程序集。编译的程序集只将其编译的字节码存储在本地缓存中。您应该仍然能够测试代码。通过使用lambda表达式而不是字符串来定义方法,您可能可以使代码不那么脆弱。我想我会把它做成一个表达式,你可以直接得到methodinfo。好主意。不过,我对表达式API没有经验。