关于不良测试的更多信息

有一天,我无意中发现了一位用户试图监控其虚拟机中 RAM 性能的代码。 我不会给出这个代码(那里有一个“脚布”),我只会留下最重要的部分。 所以,猫在工作室里!

#include <sys/time.h>
#include <string.h>
#include <iostream>

#define CNT 1024
#define SIZE (1024*1024)

int main() {
	struct timeval start;
	struct timeval end;
	long millis;
	double gbs;
	char ** buffers;
	buffers = new char*[CNT];
	for (int i=0;i<CNT;i++) {
		buffers[i] = new char[SIZE];
	}
	gettimeofday(&start, NULL);
	for (int i=0;i<CNT;i++) {
		memset(buffers[i], 0, SIZE);
	}
	gettimeofday(&end, NULL);
	millis = (end.tv_sec - start.tv_sec) * 1000 +
		(end.tv_usec - start.tv_usec) / 1000;
	gbs = 1000.0 / millis;
	std::cout << gbs << " GB/sn";
	for (int i=0;i<CNT;i++) {
		delete buffers[i];
	}
	delete buffers;
	return 0;
}

很简单 - 分配内存并向其中写入 XNUMX GB。 这个测试表明了什么?

$ ./内存测试
4.06504 GB /秒

大约 4GB/秒。

什么?!?!

如何?!?!?

这是Core i7(虽然不是最新的),DDR4,处理器几乎没有加载 - 为什么?!?!

答案一如既往地异常普通。

new 运算符(顺便说一句,就像 malloc 函数)实际上并不分配内存。 通过这个调用,分配器会查看内存池中的空闲位置列表,如果没有,则调用 sbrk() 来增加数据段,然后将新位置的地址引用返回给程序分配。

问题是分配的区域完全是虚拟的。 没有分配实际内存页。

当第一次访问这个分配的段中的每个页面时,MMU“射击”页面错误,之后正在访问的虚拟页面被分配一个真实的页面。

因此,实际上我们测试的不是总线和RAM模块的性能,而是操作系统的MMU和VMM的性能。 而为了测试RAM的真实性能,我们只需要对分配的区域进行一次初始化即可。 例如这样:

#include <sys/time.h>
#include <string.h>
#include <iostream>

#define CNT 1024
#define SIZE (1024*1024)

int main() {
	struct timeval start;
	struct timeval end;
	long millis;
	double gbs;
	char ** buffers;
	buffers = new char*[CNT];
	for (int i=0;i<CNT;i++) {
                // FIXED HERE!!!
		buffers[i] = new char[SIZE](); // Add brackets, &$# !!!
	}
	gettimeofday(&start, NULL);
	for (int i=0;i<CNT;i++) {
		memset(buffers[i], 0, SIZE);
	}
	gettimeofday(&end, NULL);
	millis = (end.tv_sec - start.tv_sec) * 1000 +
		(end.tv_usec - start.tv_usec) / 1000;
	gbs = 1000.0 / millis;
	std::cout << gbs << " GB/sn";
	for (int i=0;i<CNT;i++) {
		delete buffers[i];
	}
	delete buffers;
	return 0;
}

也就是说,我们只需使用默认值(char 0)初始化分配的缓冲区。

检查:

$ ./内存测试
28.5714 GB /秒

另一件事。

这个故事的寓意是 - 如果您需要大缓冲区才能快速工作,请不要忘记初始化它们。

来源: habr.com

添加评论