使用嵌套结构会有性能惩罚吗?

5

当我使用多个嵌套结构/类(有点像使用多维堆数组)时,是否会有性能损失?还是这只是语言的组织特性,使其更容易跟踪数据,并且编译器实际上并没有看到任何区别?

谢谢

4个回答

5
并不是。类/结构只是定义了在内存中的偏移量,所以如果你有一个类嵌套在另一个类中,编译器只需将偏移量相加即可。
性能问题出现在你使用指针时(每个指针解引用都会读取内存并可能导致L2缓存丢失),或者使用虚函数时(非常糟糕,特别是在旧CPU上)。
编辑:但需要注意的一点是 - 如果您正在开发的应用程序对性能并不是绝对关键,那么请专注于良好的类设计而不是性能。虽然像L2缓存丢失这样的事情在编写需要以60fps运行的内容时会产生很大的影响,但在普通桌面应用程序中却没有什么关联。

指针会带来一些额外的开销吗? - vol7ron
解引用它们会这样做。pA->pB->pC->pD将强制系统从四个地址中读取数据。每个地址可能在不同的缓存页中,导致昂贵的L2缓存未命中。由于您必须解引用pA才能找到pB,因此您将无法预取。但是:指针对于将很少使用的数据与主结构分开非常有用,因此如果您有一个需要经常迭代的结构数组,请将实际使用的数据保存在结构中,并将所有很少使用的内容保存在单独的类/结构中,以便您需要获取更少的缓存页。 - EboMike
虚函数调用只需要一两个内存解引用,以从vtable中获取函数地址,然后进行函数调用。性能并不比C语言中带有函数指针的结构体差得多。而像这样的结构体在Linux内核中随处可见。 - SoapBox
虚函数调用(以及函数指针调用)也无法在旧的CPU上预测,这是潜在L2缓存未命中的另一个性能损失。一般来说 - 如果您不需要某些东西是虚拟的(或回调),那么就不要以这种方式做。但是请记住我对答案所做的修改。不要为了无法衡量的性能提升而编写可怕的代码。 - EboMike

1
大多数情况下,不会有问题,正如其他人所提到的。但是,有一个小例外:将结构体放在结构体中可能会导致由于对齐问题而产生一些内存使用惩罚,相对于将相同的基元直接放入单个结构体中。这理论上可能会导致缓存未命中,从而影响性能。例如:
#include <iostream>
using namespace std;  // So sue me

struct A {
    double d;
    int i;
};

struct B {
    int j;
    int k;
    int l;
};

struct AB {
    A a;
    B b;
};

struct C {
    double d;
    int i;
    int j;
    int k;
    int l;
};

int main() {
    cout << sizeof(AB) << endl;  // 32
    cout << sizeof(C) << endl;   // 24
}

编译器优化会处理这个吗?它看起来几乎像是一种内联类型优化。 - Faken
2
编译器优化无法处理此问题,因为结构体的布局是ABI的一部分,需要进行明确定义。 - dsimcha

1

不应该有任何性能或内存惩罚。它们只是语法糖,使程序员更容易编写代码。


1

简短回答:不行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接