C# 为什么可以';这不是要优化吗?

C# 为什么可以';这不是要优化吗?,c#,performance,optimization,methods,C#,Performance,Optimization,Methods,我有一个用于添加向量的函数,如下所示: public static Vector AddVector(Vector v1, Vector v2) { return new Vector( v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); } 不太有趣。但是,我重载了向量的“+”运算符,并在重载中调用AddVector函数以避免代码重复。我很好奇这是否会导致两个方法调用,或者是否会在编译或JIT时进行优化。我发现它确实导致

我有一个用于添加向量的函数,如下所示:

public static Vector AddVector(Vector v1, Vector v2)
{
    return new Vector(
      v1.X + v2.X,
      v1.Y + v2.Y,
      v1.Z + v2.Z);
}
不太有趣。但是,我重载了向量的“+”运算符,并在重载中调用AddVector函数以避免代码重复。我很好奇这是否会导致两个方法调用,或者是否会在编译或JIT时进行优化。我发现它确实导致了两个方法调用,因为通过复制AddVector的代码以及“+”和“*”操作符重载方法中的点积方法,我成功地获得了10%的总性能。当然,这是一个利基案例,因为他们每秒被呼叫数万次,但我没想到会这样。我想我希望这个方法可以内联到另一个,或者别的什么。我想这不仅仅是方法调用的开销,还有方法参数复制到另一个方法(它们是结构)中的开销

这没什么大不了的,我可以复制代码(或者删除AddVector方法,因为我从来没有直接调用过它),但是将来当我决定为某个东西创建一个方法时,它会让我非常烦恼,比如将一个大方法拆分成几个小方法

我认为这不仅是方法调用的开销,而且是将方法参数复制到另一个方法(它们是结构)中的开销


你为什么不测试一下呢?编写一个AddVector版本,该版本引用两个vector结构,而不是结构本身

如果编译到调试模式,或者在开始过程时附加了一个调试器(尽管您可以稍后添加调试器),那么就不会出现大量的JIT优化,包括内联优化


尝试重新运行测试,方法是在发布模式下编译测试,然后在没有附加调试器的情况下运行测试(VS中的Ctrl+F5),看看是否看到了预期的优化效果。

您说的
Vector
是一个结构。根据,值类型是不内联方法的原因。我不知道在此期间规则是否已经改变。

不要认为
struct
是性能的正确选择。在某些情况下,复制成本可能很高。直到你测量你才知道。此外,
struct
s有行为,特别是当它们是可变的,但即使它们不是可变的

此外,其他人所说的是正确的:

  • 在调试器下运行将禁用JIT优化,从而使性能度量无效
  • 在调试模式下编译也会使性能度量无效

我的VS处于发布模式,我在没有调试的情况下运行,所以这不能怪我。在Release文件夹中运行.exe会产生相同的结果。我已经安装了.NET3.5SP1


我是否使用结构取决于我创建了多少东西,以及复制和引用时它有多大

我能想到的只有一个优化,也许你想要一个vOut参数,因此你可以避免调用new(),从而减少垃圾收集——当然,这完全取决于你对返回向量的处理,以及你是否需要持久化它,如果您遇到垃圾收集问题。

99%的时间,因为在这种情况下,即使10%的性能改进也可以忽略不计(内联与2个方法调用)。你的绝对绩效收益是多少?我最多只能猜几毫秒。有关示例,请参见。抱歉,我不能回答这个问题。好吧,好吧,微优化不好——但问题的答案是什么?你能用编译标志或方法属性等尝试不同的行为吗?@bnkdev:事实上我同意你的看法。事实上,我们的评论有几秒钟的时差,我没有看到你的:)我实际上是在阻止微优化;内联非托管函数调用与虚拟(托管)函数调用之间的差异约为20倍。对于实时光线跟踪器中的核心数学原语,这是巨大的!这比按值传递要慢(取决于结构大小,但我指的是推荐的大小);x64在比这个版本更早的版本中支持内联,但我不确定到底是哪一个…绝对正确。从codeproject.com将自定义向量类型更改为光线跟踪器中的类(找不到url)带来了显著的性能提升。感谢您提供的有用见解:)我刚刚将结构更改为类,瞧,显著的性能提升!我也真的没有想到,但是我会为我的问题创建一个新的问题。奇怪的是,当我从类切换到结构时,我的性能提高了10倍。因为它是一个结构,GC不是问题。唯一改变的是一些次要的堆栈使用点-但因为它是返回值,所以这一点可以忽略不计。哦,我没有意识到-干杯。