代表对代表性能过分是一个坏主意吗?

and*_*ecu 5 .net c# performance lambda delegates

请考虑以下代码:

if (IsDebuggingEnabled) { 
   instance.Log(GetDetailedDebugInfo()); 
}
Run Code Online (Sandbox Code Playgroud)

GetDetailedDebugInfo() 可能是一种昂贵的方法,所以我们只想在调试模式下运行时调用它.

现在,更清洁的替代方案是编写如下代码:

instance.Log(() => GetDetailedDebugInfo());
Run Code Online (Sandbox Code Playgroud)

其中.Log()的定义如下:

public void Log(Func<string> getMessage)
{
    if (IsDebuggingEnabled) 
    {
        LogInternal(getMessage.Invoke());
    }
}
Run Code Online (Sandbox Code Playgroud)

我关心的是性能,初步测试没有显示第二种情况特别昂贵,但如果负载增加,我不想遇到任何意外.

哦,请不要建议条件编译,因为它不适用于这种情况.

(PS:我直接在StackOverflow中写了代码问一个问题textarea所以不要责怪我,如果有微妙的错误,它没有编译,你明白了:)

Meh*_*ari 5

不,它应该没有糟糕的表现.毕竟,只有在性能不是最重要的调试模式下才会调用它.实际上,您可以删除lambda并只传递方法名称以消除不必要的中间匿名方法的开销.

请注意,如果要在Debug版本中执行此操作,可以[Conditional("DEBUG")]向log方法添加属性.


and*_*ecu 3

我希望获得一些有关这种情况下性能的文档,但似乎我得到的只是有关如何改进我的代码的建议......似乎没有人读过我的 PS - 没有给你分。

所以我写了一个简单的测试用例:

    public static bool IsDebuggingEnabled { get; set; }


    static void Main(string[] args)
    {
        for (int j = 0; j <= 10; j++)
        {
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i <= 15000; i++)
            {
                Log(GetDebugMessage);
                if (i % 1000 == 0) IsDebuggingEnabled = !IsDebuggingEnabled;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
        }

        Console.ReadLine();
        for (int j = 0; j <= 10; j++)
        {
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i <= 15000; i++)
            {
                if (IsDebuggingEnabled) GetDebugMessage();
                if (i % 1000 == 0) IsDebuggingEnabled = !IsDebuggingEnabled;
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
        }
        Console.ReadLine();
    }

    public static string GetDebugMessage()
    {
        StringBuilder sb = new StringBuilder(100);
        Random rnd = new Random();
        for (int i = 0; i < 100; i++)
        {
            sb.Append(rnd.Next(100, 150));
        }
        return sb.ToString();
    }

    public static void Log(Func<string> getMessage)
    {
        if (IsDebuggingEnabled)
        {
            getMessage();
        }
    }
Run Code Online (Sandbox Code Playgroud)

两个版本之间的时间似乎完全相同。我在第一种情况下得到 145 毫秒,在第二种情况下得到 145 毫秒

看来我回答了我自己的问题。