【发布时间】:2018-10-28 04:12:09
【问题描述】:
我一直想知道如何处理这个问题已经有一段时间了,但我找不到一个优雅的解决方案。我认为一些例子是理解问题的最简单方法。
假设我们在一个类中有这段代码,当调用它们的函数时,x 和 y 需要从 0 开始:
// here we have x as a local variable
private void functionX() {
int x = 0;
// ...
// do stuff with x
// ...
}
// here we have y as an out of function scope variable
int y;
private void functionY() {
y = 0;
// ...
// do stuff with y
// ...
}
public void update()
{
// this is slower because x gets a new instance every time functionX gets called
for (int i = 0; i < 100000; i++) {
functionX();
}
// this is faster because y gets only one instance before the function ever gets called
for (int i = 0; i < 100000; i++) {
functionY();
}
}
我已经测试了这段代码,并使用函数范围外的变量而不是使用局部变量产生了更好的性能(尽管在这个例子中不是很多,但仍然有性能提升)。缺点是您必须在函数范围外部声明函数变量才能获得这种性能提升,这会使您的代码更混乱且更容易出错。
这只是一个非常简单的示例,但是如果您有数千行代码,其中包含大量此类函数变量,并且将它们超出函数范围所带来的性能提升不容忽视,但您因拥有而造成的混乱所有这些超出范围的变量也不能被忽略吗?是否有解决此问题的方法,或者您必须在性能和可读性/稳健性之间做出选择?
ps.当您必须从它们所在的类构造多个对象时,在其函数中制作 x 或 y 静态变量也不起作用(您的所有对象都将具有x 和 y 表示整个程序运行时)
编辑:进一步简化代码
【问题讨论】:
-
交换 functionX 和 functionY 循环的顺序,这样你首先调用 Y 并重新测试,我打赌你会看到 X 变得更快。在这种人为的情况下进行测试很难正确进行。
-
functionY的性能应该更好的唯一原因是:y = 0只有一个赋值;在functionX中是两次分配,因为int x;已经将零分配给x,然后您第二次手动分配它。还有一个。y变量与类一起编译,但x变量仅在首次使用时编译。在循环之前再调用一次functionX和functionY,以提前编译函数。 -
如果您有数千行代码,如
FunctionY,那么您遇到的问题远不止性能差异那么大。 -
我其实很喜欢微优化问题,但是这里没有什么可以优化的 :( 话虽如此,你在另一个方法的范围内创建的每个变量都将在堆栈上创建,并且将是一个分配,并且会占用早熟的 CPU 周期。但是,创建这些 Instance 字段是一个坏主意,您已经停止了并行此操作的任何机会。
-
I tested on debug mode initially从不在调试模式下测试性能。这完全是浪费时间。
标签: c# performance optimization scope local-variables