访问类成员时的性能

时间:2010-05-19 16:35:00

标签: c++ micro-optimization

我正在撰写一些对性能至关重要的内容,并想知道如果我使用它会是否会产生影响:

int test( int a, int b, int c )
{
    // Do millions of calculations with a, b, c
}

class myStorage
{
public:
  int a, b, c;
};

int test( myStorage values )
{
   // Do millions of calculations with values.a, values.b, values.c
}
  • 这基本上会产生类似的代码吗?访问班级成员是否有额外的开销?

我确信这对C ++专家来说很明显,所以我现在不会尝试为它写一个不切实际的基准

8 个答案:

答案 0 :(得分:5)

编译器可能会对它们进行均衡。如果它有任何大脑,它会将values.avalues.bvalues.c复制到局部变量或寄存器中,这也是简单情况下的情况。

相关格言:

  1. 过早优化是多恶的根源。

  2. 写下来,以便您可以在六个月后的凌晨1点阅读,并且仍然能理解您的目的。

  3. 大多数情况下,重要的优化来自重构算法,而不是变量访问方式的微小变化。是的,我知道有例外,但这可能不是其中之一。

答案 1 :(得分:4)

这听起来像是过早优化。

话虽如此,但存在一些差异和机会,但它们会影响对函数的多次调用,而不是函数中的性能。

首先,在第二个选项中,您可能希望将MyStorage作为常量引用传递。 因此,您编译的代码可能会将单个值压入堆栈(以允许您访问容器),而不是推送三个单独的值。如果你有其他字段(除了a-c),发送MyStorage不作为参考实际上可能会花费更多,因为你将调用一个复制构造函数并基本上复制所有其他字段。所有这些都是每次通话的费用,而不是在功能范围内。

如果你在函数中使用b和c进行大量计算,那么转移或访问它们的方式并不重要。如果你通过引用传递,初始成本可能稍微多一些(因为你的对象,如果通过引用传递,可能在堆而不是堆栈上),但是一旦第一次访问,你的机器上的缓存和寄存器可能会意味着低成本访问。如果你已经按值传递了对象,那么它确实无关紧要,因为即使最初,这些值也会在堆栈附近。

对于您提供的代码,如果这些是唯一的字段,则可能没有区别。 “values.variable”仅被解释为堆栈中的偏移量,而不是“查找一个对象,然后访问另一个地址”。

当然,如果您不购买这些参数,只需将局部变量定义为函数的第一步,复制对象中的值,然后使用这些变量。如果你真的多次使用它们,这个副本的初始成本无关紧要:)

答案 2 :(得分:0)

不,你的cpu会缓存你一遍又一遍使用的变量。

答案 3 :(得分:0)

我认为有一些开销,但可能不会太多。因为对象的内存地址将存储在指向堆内存对象的堆栈中,所以您可以访问实例变量。

如果将变量int存储在堆栈中,它会更快,因为该值已经在堆栈中,并且机器只是去堆栈以计算出来:)。

它还取决于您是否将类的实例变量值存储在堆栈上。如果在test()中,你会喜欢:

int a = objA.a;
int b = objA.b;
int c = objA.c;

我认为这几乎是相同的表现

答案 4 :(得分:0)

如果您真的在编写性能关键代码,并且您认为一个版本应该比另一个版本更快,请编写两个版本并测试时序(使用正确的优化开关编译代码)。您甚至可能希望查看生成的汇编代码。很多事情都会影响代码片段的速度,这些代码片段非常微妙,比如寄存器溢出等。

答案 5 :(得分:0)

你也可以用

开始你的功能
int & a = values.a;
int & b = values.b;

虽然编译器应该足够聪明,可以在幕后为您完成。一般来说,我更喜欢传递结构或类,这使得函数通常更清楚,而且每次想要考虑另一个参数时都不必更改签名。

答案 6 :(得分:0)

与之前的类似问题一样:它取决于编译器和平台。如果有任何差异,它将非常小。

堆栈上的值和对象中的值通常使用指针(堆栈指针或this指针)和一些偏移量(函数的堆栈框架中的位置,或者内部的位置)来访问类)。

以下是一些可能会产生影响的案例:

  • 根据您的平台,堆栈指针可能保存在CPU寄存器中,而this指针可能不会。如果是这种情况,访问this(可能在堆栈上)将需要额外的内存查找。

  • 内存位置可能不同。如果内存中的对象大于一个缓存行,则字段将分布在多个缓存行中。在堆栈帧中仅将相关值放在一起可能会提高缓存效率。

请注意,我在这里经常使用“可能”这个词。唯一可以确定的方法就是测量它。

答案 7 :(得分:0)

如果无法对程序进行概要分析,请打印出代码片段的汇编语言。

通常,较少的汇编代码意味着执行的指令较少,从而加快了性能。当分析器不可用时,这是一种粗略估计性能的技术。

汇编语言列表将允许您查看实现之间的差异(如果有)。