關於不良測試的更多信息

有一天,我無意中發現了一位用戶試圖監控其虛擬機器中 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 / s

大約 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 / s

另一件事。

這個故事的寓意是——如果您需要大緩衝區才能快速工作,請不要忘記初始化它們。

來源: www.habr.com

添加評論