Sedikit lagi tentang ujian buruk

Pada suatu hari saya secara tidak sengaja terjumpa kod yang pengguna cuba memantau prestasi RAM dalam mesin mayanya. Saya tidak akan memberikan kod ini (terdapat "kain kaki" di sana) dan saya akan meninggalkan yang paling penting sahaja. Jadi, kucing itu berada di dalam studio!

#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;
}

Ia mudah - peruntukkan memori dan tulis satu gigabait ke dalamnya. Dan apakah yang ditunjukkan oleh ujian ini?

$ ./memtest
4.06504 GB / s

Kira-kira 4GB/s.

Apa?!?!

Bagaimana?!?!?

Ini adalah Core i7 (walaupun bukan yang terbaru), DDR4, pemproses hampir tidak dimuatkan - KENAPA?!?!

Jawapannya, seperti biasa, adalah luar biasa biasa.

Pengendali baru (seperti fungsi malloc, dengan cara itu) sebenarnya tidak memperuntukkan memori. Dengan panggilan ini, pengalokasi melihat senarai lokasi percuma dalam kolam memori, dan jika tiada, panggil sbrk() untuk meningkatkan segmen data, dan kemudian kembali ke program rujukan kepada alamat dari lokasi baharu hanya diperuntukkan.

Masalahnya ialah kawasan yang diperuntukkan adalah maya sepenuhnya. Tiada halaman memori sebenar diperuntukkan.

Dan apabila akses pertama kepada setiap halaman daripada segmen yang diperuntukkan ini berlaku, MMU "menembak" kesalahan halaman, selepas itu halaman maya yang diakses diberikan yang sebenar.

Oleh itu, sebenarnya, kami tidak menguji prestasi modul bas dan RAM, tetapi prestasi MMU dan VMM sistem pengendalian. Dan untuk menguji prestasi sebenar RAM, kita hanya perlu memulakan kawasan yang diperuntukkan sekali. Contohnya seperti ini:

#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;
}

Iaitu, kita hanya memulakan penimbal yang diperuntukkan dengan nilai lalai (char 0).

Kami menyemak:

$ ./memtest
28.5714 GB / s

Perkara lain.

Moral of the story - jika anda memerlukan penimbal besar untuk berfungsi dengan cepat, jangan lupa untuk memulakannya.

Sumber: www.habr.com

Tambah komen