【发布时间】:2011-02-07 12:49:00
【问题描述】:
我不确定主题是否正确,但我会尝试在下面解释我的问题。我正在寻找的是某种“学术答案”,因为我认为我的两种解决方案在运行时都会给出相似的结果。
我在 Linux 上有一个 C++ 程序,它执行大量网络 I/O 操作,我想知道将缓冲区内置到客户端类中还是动态分配它更好。使用内置缓冲区的第一个解决方案:
template <size_t buffer_size> class Buffer
{
// ...
char buffer [buffer_size];
}
class TcpClient
{
// ...
Buffer<1024> input_buffer;
Buffer<1024> output_buffer;
}
第二次使用动态分配的缓冲区:
class Buffer
{
Buffer (size_t buffer_size) :
buffer (malloc (buffer_size))
{
// ...
}
// ...
char* buffer;
}
class TcpClient
{
// ...
Buffer input_buffer (1024);
Buffer output_buffer (1024);
}
现在,比较这两种解决方案,我发现首先需要更少的内存分配操作,然后是第二个,接下来的事情 - 多亏了模板编译器在编译时知道类大小。第一个解决方案应该提供更好的参考局部性(?),编译器还可以根据需要调整类大小。我们还可以直接访问缓冲区,因为我们不需要执行额外的指针取消引用操作。
我开始思考第一个解决方案中的 TcpClient 对象在处理器缓存中的行为方式。每次我们在代码中访问这样的对象时,它都会被加载到处理器缓存中,并且它的缓冲区也会被复制,即使我们不需要它们。它会使缓存效率低下,因为我们在那里存储了大量数据,这会增加内存查找错误的概率,对吧?
一直将缓冲区复制到缓存不是浪费处理器的时间吗? 从处理器和操作系统的角度来看,这两种解决方案的其他影响是什么? 保持班级规模小还是尽可能多地构建它更好?
【问题讨论】:
-
您可以在堆栈上分配缓冲区,使用您的类的成员。顺便说一句,您编写 C++ 代码时,请使用 new,而不是 malloc!
-
“每次我们在代码中访问这样的对象时,它都会被加载到处理器缓存中,并且它的缓冲区也会被复制” - 这并不完全正确。在我能想到的任何架构上,无论对象在哪里,内存都由固定大小的页面/行(取决于缓存)缓存。使用一条线,该线已加载。如果您要创建一个
TcpClient对象数组,并对它们执行大量不使用缓冲区的操作,那么外部缓冲区可能意味着您可以在一个排队并加快速度。否则,该帐户没有区别。
标签: c++ memory-management