使用静态类成员而不是私有字段之间的速度差异是什么?

What is the speed difference between using static class members instead of private fields?

本文关键字:速度 之间 是什么 字段 成员 静态类      更新时间:2023-10-16

>我正在编写一个应用程序,其中我有静态配置类:

class Device {
public:
static Device &getInstance() {
static Device    instance; 
return instance;
}
private:
Device() {
init();
}
void init() {
this->ramps_count = 300;
this->gates = 64;
}
public:
Device ( Device const & ) = delete;
void operator= ( Device const & ) = delete;
int ramps_count;
int gates;
};

此类用于获取和设置我的设备配置。当然,此类中还有其他字段。对我来说,它是静态的非常重要,因为我在很多地方都在使用这些字段,而且以这种方式使用它很方便。此外,我有将此配置保存和加载到/从文件加载的功能。

另一方面,我有一个经常使用此配置的类。我的应用程序有一个主循环,其中调用了此类:

class FrameFFTProcessor : public FrameProcessor {
public:
FrameFFTProcessor (){
}
void process ( ) {
for(int i=0; i<Device::getInstance().ramps_count; i++){
for(int i=0; i<Device::getInstance().gates; i++){
//... doint it's job
// and somethimes using values 
// Device::getInstance().ramps_count and gates 
}
}
}
private:
};

所以我认为最好将这些字段放在本地(在我的类中),这样我就不必使用 static 成员获取它,我将我的实现更改为:

class FrameFFTProcessor : public FrameProcessor {
public:
FrameFFTProcessor (){
this->ramps_count = Device::getInstance().ramps_count;
this->gates = Device::getInstance().gates;
}
void process ( ) {
for(int i=0; i<ramps_count; i++){
for(int i=0; i<gates; i++){
//... doint it's job
// and somethimes using values 
// Device::getInstance().ramps_count and gates 
}
}
}
private:
// private rewrite
size_t ramps_count;
size_t gates;
};

所以我的问题是 - 它更好/更快更有效吗?我应该将这些值复制到私有字段,还是调用静态实例更好(性能)?

请记住,我有 50 多个配置字段,它们用于 10 个不同的处理器(类扩展FrameProcessor)。

有没有更好的方法可以做到这一点?

不建议将静态配置值存储为其他类(配置类除外)的成员。类(例如FrameProcessor)应保持数据与其相关,而不是其他任何内容。您可以在process方法中获取Device配置类的引用/指针,并使用数据值。

void process ( ) 
{
const Device& devConfig = Device::getInstance();
for(int i=0; i<devConfig.ramps_count; i++){
for(int i=0; i<devConfig.gates; i++){
...

但是,Device类存在问题:

  • 数据成员作为公共变量公开,任何人都可以更改它(可能是无意的)。您应该提供访问器方法 (const)。
  • 该类不是线程安全的。您要么需要使其线程安全,要么需要确保每个线程都有自己的副本(此决定完全根据需要)。

您可以编写用于数据访问的方法,也可以使方法线程安全。

如果您的程序是单线程的,那么第一种方法似乎更快,因为您不会花时间将整个资源复制到类对象,而只是直接访问变量。编译器通常会优化 getter 函数,让调用方直接访问变量

这完全取决于您的缓存使用情况。

如果您的访问都在内存中紧密地在一起,则系统可以缓存它们。如果它们是分散的,它必须从内存芯片中获取,这是最昂贵的原子操作 - 我们谈论的是比缓存访问慢十倍。

通过将字段设置为静态,您可以将它们放在单独的内存区域中。但这可能有助于或阻碍您的缓存,具体取决于它决定如何填充自己。

访问类的成员或单例的成员具有几乎相同的间接级别,您应该以局部变量为目标,以几乎强制编译器使用寄存器。

我认为可以保持最佳速度而不必将设备内部值存储在处理器对象中的解决方案(正如其他人所说是一件坏事)是......倒数:

void process() {
int i = Device::getInstance().ramps_count;
for(;i > 0; --i){
int j = Device::getInstance().gatesl;
for(; j > 0; --j){
//... doint it's job
// and somethimes using values 
// Device::getInstance().ramps_count and gates 
}
}
}

这也更快,因为检查一个值,大概在寄存器内部是否不同于零,它不需要内存访问,而检查它与非常量值不同需要它(缓存访问也比没有访问慢)。

我不是在发明这个,大多数绘制算法都这样做。

还请重视为您的访问器构建 const 方法,即:

class Device {
[...]
public:
int getGateSL() const { return gatesl; }
int getRampCounts() const { return ramp_count; }
[...]
}

因为编译器的优化器可以在 const 方法上做更积极的工作。