当前位置:  开发笔记 > 编程语言 > 正文

访问成员变量与局部变量的C++性能

如何解决《访问成员变量与局部变量的C++性能》经验,为你挑选了2个好方法。

类访问成员变量或局部变量更有效吗?例如,假设您有一个(回调)方法,其唯一的职责是接收数据,对其执行计算,然后将其传递给其他类.在性能方面,有一个成员变量列表更有意义,该方法在接收数据时填充?或者只是在每次调用回调方法时声明局部变量?

假设这种方法每秒会被调用数百次......

如果我不清楚,这里有一些简单的例子:

// use local variables
class thisClass {
    public:
        void callback( msg& msg )
        {
            int varA;
            double varB;
            std::string varC;
            varA = msg.getInt();
            varB = msg.getDouble();
            varC = msg.getString();

            // do a bunch of calculations
         }

};

// use member variables
class thisClass {
    public:
        void callback( msg& msg )
        {
             m_varA = msg.getInt();
             m_varB = msg.getDouble();
             m_varC = msg.getString();

             // do a bunch of calculations
        }

    private:
        int m_varA;
        double m_varB;
        std::string m_varC;

};

peterchen.. 47

执行摘要:在几乎所有场景中,无关紧要,但局部变量略有优势.

警告:您正在进行微观优化.你最终会花费数小时试图理解本应该赢得纳秒的代码.

警告:在您的场景中,性能不应该是问题,而是变量的作用 - 它们是临时的,还是thisClass的状态?

警告:优化的第一,第二和最后一条规则:措施!


首先,看看为x86生成的典型程序集(您的平台可能会有所不同):

// stack variable: load into eax
mov eax, [esp+10]

// member variable: load into eax
mov ecx, [adress of object]
mov eax, [ecx+4]

一旦加载了对象的地址,在寄存器中,指令是相同的.加载对象地址通常可以与先前的指令配对,并且不会达到执行时间.

但这意味着ecx寄存器不可用于其他优化.然而,现代CPU做了一些强烈的诡计,以减少问题.

此外,当访问许多对象时,这可能会花费额外的费用.然而,这不到一个周期平均值,并且配对指令通常有更多的机会.

记忆局部性:这是筹码赢得大时间的机会.堆栈顶部几乎总是在L1缓存中,因此负载需要一个周期.该对象更有可能被推回到L2缓存(经验法则,10个周期)或主存储器(100个周期).

但是,您只需为第一次访问付费.如果只有一次访问,则10或100个循环是不可察觉的.如果你有成千上万的访问,对象数据也将在L1缓存中.

总之,增益是如此之小,以至于将成员变量复制到本地以实现更好的性能几乎没有意义.



1> peterchen..:

执行摘要:在几乎所有场景中,无关紧要,但局部变量略有优势.

警告:您正在进行微观优化.你最终会花费数小时试图理解本应该赢得纳秒的代码.

警告:在您的场景中,性能不应该是问题,而是变量的作用 - 它们是临时的,还是thisClass的状态?

警告:优化的第一,第二和最后一条规则:措施!


首先,看看为x86生成的典型程序集(您的平台可能会有所不同):

// stack variable: load into eax
mov eax, [esp+10]

// member variable: load into eax
mov ecx, [adress of object]
mov eax, [ecx+4]

一旦加载了对象的地址,在寄存器中,指令是相同的.加载对象地址通常可以与先前的指令配对,并且不会达到执行时间.

但这意味着ecx寄存器不可用于其他优化.然而,现代CPU做了一些强烈的诡计,以减少问题.

此外,当访问许多对象时,这可能会花费额外的费用.然而,这不到一个周期平均值,并且配对指令通常有更多的机会.

记忆局部性:这是筹码赢得大时间的机会.堆栈顶部几乎总是在L1缓存中,因此负载需要一个周期.该对象更有可能被推回到L2缓存(经验法则,10个周期)或主存储器(100个周期).

但是,您只需为第一次访问付费.如果只有一次访问,则10或100个循环是不可察觉的.如果你有成千上万的访问,对象数据也将在L1缓存中.

总之,增益是如此之小,以至于将成员变量复制到本地以实现更好的性能几乎没有意义.


C ++没有特定的ABI。但是我读过的总是为this指针保留一个。所以没有收获。另外,您会忘记复制到本地人/从本地人中复制的成本。

2> fizzer..:

我更喜欢局部变量的一般原则,因为它们可以最大限度地减少程序中的恶变状态.至于性能,您的探查器会告诉您需要知道的所有信息.对于整数和其他内置函数,本地应该更快,因为它们可以放在寄存器中.

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有