线程缓存的对象引用
Thread-cached object referencing
我需要创建一种共享对象(无论出于何种原因)。它并不局限于单线程的使用。通常在这种情况下,联锁操作是可行的(例如Win32上的InterlockedIncrement
和InterlockedDecrement
)。
尽管对象引用计数在任何情况下都应该正确工作,但我想针对单线程使用对其进行优化。联锁操作比标准算术操作要重得多。从我的测量中,一个联锁操作(发出全内存屏障)在我的"典型"CPU上大约需要40个CPU周期,而标准算术操作低于任何测量精度(多亏了CPU缓存)。
在内存分配方面也有类似的技术。有一些堆实现,比如"TCMalloc",它由集中的内存分区机制组成,由适当的同步对象保护,再加上每个线程的缓存。在最常见的情况下,在每个线程缓存上分配/释放内存,这根本不涉及任何联锁操作,而且CPU缓存的利用率很高。
因此,我考虑为支持引用的对象做类似的事情的可能性。有什么办法做到这一点吗?我们也欢迎你的原创想法。
在我的场景中,如果可以提高性能,可以将实际的对象销毁延迟一段时间。
我就不麻烦了。我刚刚运行了这个基准测试:
#include<stdio.h>
#define SIZE 1000000
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
void print_avg(const char *str, const int *diff, int size)
{
int i;
long sum = 0;
int max = -1, min = 10000;
for(i = 0; i < size; i++)
{
int t = diff[i];
sum += t;
if (t > max) max = t;
if (t < min) min = t;
}
printf("%s average =%f clocks, max =%d, min =%dn", str, (double)sum / size, max, min);
}
int main()
{
unsigned long long a, b;
int diff[SIZE];
int value = 0;
int i;
for(i = 0; i < SIZE; i++)
{
a = rdtsc();
__sync_fetch_and_add(&value, 2);
b = rdtsc();
diff[i] = (int)(b - a);
}
print_avg("Locked", diff, SIZE);
for(i = 0; i < SIZE; i++)
{
a = rdtsc();
value += 2;
b = rdtsc();
diff[i] = (int)(b - a);
}
print_avg("Not locked", diff, SIZE);
return 0;
}
使用gcc -O2编译,它给出以下结果:
Locked average =105.672402 clocks, max =38756, min =86
Not locked average =80.540389 clocks, max =23433, min =73
我运行了几次,每次的结果都非常相似。请忽略max的大数字-这是处理器中断或其他事情的时候-它来自我为不同目的编写的一些代码,我只是在这个测试中循环使用它。这个微小的差异应该适用于所有现代处理器(Intel iCore和AMD Athlon64等几代处理器)
除非你的编译器没有内联InterlockedIncrement,否则在你的代码中添加if语句很可能会花费至少5个周期,所以你最多节省了10个周期。希望您正在做的不是增加和减少引用计数器。
编辑:添加内存屏障也不会产生很大的差异-大约10个周期。
不可否认,如果我在第二个循环中添加10个加法,那么每个循环大约有5个时钟周期(因此平均每次添加半个时钟),而锁定的加法每次添加大约需要20个时钟。在我看来,仍然不值得添加if语句。但是如果你想添加"if (nr_threads == 1) a = a + 1;else a = __sync_fetch_and_add(a, 1);",[或任何你需要做的事]我不会阻止你。但要确保对整个应用程序进行基准测试,并确保改进幅度超过1%——我对此表示怀疑。请务必回来告诉我们有什么不同。我在Linux内核的"deallocate页表项"中添加的if语句使它慢了2-5%,所以不值得这样做。但如果您在代码中发现了这一点,那就值得了,随您的便。我是根据我的经验说的,我有数据可以证明这一点,但如果你想自己尝试一下,当然可以。
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- C++对象引用返回不同的值
- 对象引用中的字段以不同的方法返回不同的值
- 通过向构造函数其他对象引用页面来创建对象
- 为什么在对象引用恒定时允许更改为另一个类的指针的成员变量
- 如何在C++中读取 HDF5 对象引用
- C++ 未定义的对象引用
- 从函数返回 libconfig 类设置对象引用
- qt vsaddin错误对象引用未设置为对象的istanse
- 在这种情况下,为什么使用 *此必需的对象引用返回对象引用
- 基本C - 构造contaning对象引用,并将其作为方法参数传递
- C :将对象引用作为参数给出错误:呼叫class :: function()的匹配函数
- C++OOP基础知识-是否正确返回对象引用
- 使用对象引用(可能)在调用destructor后使用对象引用
- 创建返回对象引用的成员函数的最简单方法
- 如何在C++上使用对象引用删除对象
- JNI/Android NDK-维护全局对象引用
- 为什么有些类方法返回"*this"(self的对象引用)?
- 线程缓存的对象引用