C++线程本地计数器实现
c++ thread local counter implement
我想在多线程进程中实现一个高性能计数器,像这样,每个线程都有一个名为“t_counter”的线程本地计数器来计算查询(incr 1/query)和“定时器线程” “有一个名为“global_counter”的计数器,我想要的是每秒,global_counter 将获取每个 t_counter(s) 并将它们添加到 global_counter,但我不知道如何在“计时器线程”中获取每个 t_counter 值。另外,哪个部分将线程本地值放在主内存中? .data 或堆或其他?如何动态分配内存大小(可能有 10 个线程或 100 个线程)? x86-64 使用段寄存器存储这样的值吗?
从你的第二个问题开始,你可以找到所有规格 here。
综上所述,线程局部变量定义在.tdata / .tbss中。这些有点类似于 .data,但是访问它们是不同的。这些部分按线程复制。实际变量偏移量是在运行时计算的。
变量由 .tdata 中的偏移量标识。说到x86_64它会使用FS段寄存器找到TCB(线程控制块),使用存储在那里的数据结构它会定位变量所在的线程本地存储。请注意,如果可能,所有分配都是延迟完成的。
现在,关于你的第一个问题——我不知道有什么方法可以只列出来自另一个线程的所有线程局部变量,我怀疑它是否可用。
但是,线程可以获取指向线程变量的指针,并将其传递给另一个线程。所以你可能需要的是一些注册机制。
每个新线程都会将自己注册到某个主存储,然后在终止时注销。注册和注销由您负责。
从示意图上看,它看起来像这样:
thread_local int counter = 0;
std::map<std::thread::id, int *> regs;
void register() {
// Take some lock here or other synchronization, maybe RW lock
regs[std::this_thread::get_id()] = &counter;
}
void unregister() {
// Again, some lock or other synchronization
regs.erase(std::this_thread::get_id());
}
void thread_main() {
register();
counter++;
unregister();
}
void get_sum() {
// Again, some lock, maybe only read lock
return std::accumulate(regs.begin(), regs.end(), 0,
[](int previous, const auto& element)
{ return previous + *element.second; });
}
我想在多线程进程中实现一个高性能计数器,像这样,每个线程都有一个名为“t_counter”的线程本地计数器来计算查询(incr 1/query)和“定时器线程” “有一个名为“global_counter”的计数器,我想要的是每秒,global_counter 将获取每个 t_counter(s) 并将它们添加到 global_counter,但我不知道如何在“计时器线程”中获取每个 t_counter 值。另外,哪个部分将线程本地值放在主内存中? .data 或堆或其他?如何动态分配内存大小(可能有 10 个线程或 100 个线程)? x86-64 使用段寄存器存储这样的值吗?
从你的第二个问题开始,你可以找到所有规格 here。
综上所述,线程局部变量定义在.tdata / .tbss中。这些有点类似于 .data,但是访问它们是不同的。这些部分按线程复制。实际变量偏移量是在运行时计算的。
变量由 .tdata 中的偏移量标识。说到x86_64它会使用FS段寄存器找到TCB(线程控制块),使用存储在那里的数据结构它会定位变量所在的线程本地存储。请注意,如果可能,所有分配都是延迟完成的。
现在,关于你的第一个问题——我不知道有什么方法可以只列出来自另一个线程的所有线程局部变量,我怀疑它是否可用。
但是,线程可以获取指向线程变量的指针,并将其传递给另一个线程。所以你可能需要的是一些注册机制。
每个新线程都会将自己注册到某个主存储,然后在终止时注销。注册和注销由您负责。
从示意图上看,它看起来像这样:
thread_local int counter = 0;
std::map<std::thread::id, int *> regs;
void register() {
// Take some lock here or other synchronization, maybe RW lock
regs[std::this_thread::get_id()] = &counter;
}
void unregister() {
// Again, some lock or other synchronization
regs.erase(std::this_thread::get_id());
}
void thread_main() {
register();
counter++;
unregister();
}
void get_sum() {
// Again, some lock, maybe only read lock
return std::accumulate(regs.begin(), regs.end(), 0,
[](int previous, const auto& element)
{ return previous + *element.second; });
}