这些代码示例中的哪一个具有更好的性能?

时间:2009-01-01 08:04:46

标签: c# performance

在对one of my questions的回复中,我收到了一些答案,说样式2可能比样式1表现更好。我不明白怎么样,因为我认为它们应该发出基本相同的机器指令(如果写的话)在C ++)。你能解释为什么风格2可能表现更好吗?

我会在这里重写这两种风格以便于参考:

样式1

while (!String.IsNullOrEmpty(msg = reader.readMsg()))
{
    RaiseMessageReceived();
    if (parseMsg)
    {
        ParsedMsg parsedMsg = parser.parseMsg(msg);
        RaiseMessageParsed();
        if (processMsg)
        {
            process(parsedMsg);
            RaiseMessageProcessed();
        }
    }
}

样式2:

while (!String.IsNullOrEmpty(msg = reader.readMsg()))
{
    RaiseMessageReceived();
    if (!parseMsg) continue;

    ParsedMsg parsedMsg = parser.parseMsg(msg);
    RaiseMessageParsed();
    if (!processMsg) continue;

    process(parsedMsg);
    RaiseMessageProcessed();
}

6 个答案:

答案 0 :(得分:10)

如果它完全不同,我认为表现会有不同的差别。无论如何,编译器可以将它们优化为相同的形式。

唯一的实质性区别是风格。

我喜欢样式1只是因为循环有一个入口点(每次迭代)和一个出口点(每次迭代)所以很容易在循环结束时插入调试代码并知道它将被调用。这与函数的一个入口和出口点背后的原理相同(出于同样的原因)。尽管如此,虽然太多的缩进可能难以阅读,所以继续也有它的位置。

答案 1 :(得分:4)

我必须检查一下。

这是我的代码版本:

using System;
using System.Collections.Generic;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Tester t=new Tester();
            t.Method1(new Stack<string>(), new MsgParser(), true, true);
            t.Method2(new Stack<string>(), new MsgParser(), true, true);
        }
    }
    class Tester
    {
        public void Method1(Stack<string> strings, MsgParser parser, bool parseMsg, bool processMsg)
        {
            string msg;
            while (!String.IsNullOrEmpty(msg = strings.Pop()))
            {
                RaiseMessageReceived();
                if (parseMsg)
                {
                    ParsedMsg parsedMsg = parser.ParseMsg(msg);
                    RaiseMessageParsed();
                    if (processMsg)
                    {
                        process(parsedMsg);
                        RaiseMessageProcessed();
                    }
                }
            }
        }

        public void Method2(Stack<string> strings, MsgParser parser, bool parseMsg, bool processMsg)
        {
            string msg;
            while (!String.IsNullOrEmpty(msg = strings.Pop()))
            {
                RaiseMessageReceived();
                if (!parseMsg) continue;

                ParsedMsg parsedMsg = parser.ParseMsg(msg);
                RaiseMessageParsed();
                if (!processMsg) continue;

                process(parsedMsg);
                RaiseMessageProcessed();
            }

        }

        private void RaiseMessageProcessed()
        {
            Console.WriteLine("Done");
        }

        private void process(ParsedMsg msg)
        {
            Console.WriteLine(msg);
        }

        private void RaiseMessageParsed()
        {
            Console.WriteLine("Message parsed");
        }

        private void RaiseMessageReceived()
        {
            Console.WriteLine("Message received.");
        }
    }

    internal class ParsedMsg
    {
    }

    internal class MsgParser
    {
        public ParsedMsg ParseMsg(string msg)
        {
            return new ParsedMsg();
        }
    }
}

我使用代码优化(默认版本配置)构建它,并使用Reflector反汇编程序集。 结果验证两种样式是否相同:

internal class Tester
{
    // Methods
    public void Method1(Stack<string> strings, MsgParser parser, bool parseMsg, bool processMsg)
    {
        string msg;
        while (!string.IsNullOrEmpty(msg = strings.Pop()))
        {
            this.RaiseMessageReceived();
            if (parseMsg)
            {
                ParsedMsg parsedMsg = parser.ParseMsg(msg);
                this.RaiseMessageParsed();
                if (processMsg)
                {
                    this.process(parsedMsg);
                    this.RaiseMessageProcessed();
                }
            }
        }
    }

    public void Method2(Stack<string> strings, MsgParser parser, bool parseMsg, bool processMsg)
    {
        string msg;
        while (!string.IsNullOrEmpty(msg = strings.Pop()))
        {
            this.RaiseMessageReceived();
            if (parseMsg)
            {
                ParsedMsg parsedMsg = parser.ParseMsg(msg);
                this.RaiseMessageParsed();
                if (processMsg)
                {
                    this.process(parsedMsg);
                    this.RaiseMessageProcessed();
                }
            }
        }
    }

    private void process(ParsedMsg msg)
    {
        Console.WriteLine(msg);
    }

    private void RaiseMessageParsed()
    {
        Console.WriteLine("Message parsed");
    }

    private void RaiseMessageProcessed()
    {
        Console.WriteLine("Done");
    }

    private void RaiseMessageReceived()
    {
        Console.WriteLine("Message received.");
    }
}

答案 2 :(得分:3)

最好的答案是查看生成的字节码/汇编并查看。然后忽略你看到的内容,因为优化的JIT编译器无论如何都会根据执行代码的实时分析来改变它。所以坚持最能表达意图的风格。

那就是说,样式2应该直接跳回到条件,而样式1可以想象跳过if块只是为了再次跳到条件。

这必须是不过早优化我所见过的最好的例子。

答案 3 :(得分:0)

表现应该是相同的,否则谁说的一定是......困惑。

答案 4 :(得分:0)

为什么不从杰夫的书中抽出一片叶子来计算this question中的两段代码呢?

答案 5 :(得分:0)

代码流似乎相同,字节码应该相同。

免责声明:我是C / C ++程序员,我不是真的做C#