Муу тестийн талаар бага зэрэг илүү

Нэг өдөр би санамсаргүй байдлаар хэрэглэгч виртуал машиндаа 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;
}

Энэ нь энгийн зүйл юм - санах ойг хуваарилж, түүнд нэг гигабайт бичээрэй. Мөн энэ шалгалт юу харуулж байна вэ?

$./memtest
4.06504 GB / s

Ойролцоогоор 4 ГБ/с.

Юу?!?!

Хэрхэн?!?!?

Энэ бол Core i7 (хамгийн сүүлийн үеийнх биш ч гэсэн), DDR4, процессор нь бараг ачаалагдаагүй байна - ЯАГААД ?!?!

Хариулт нь урьдын адил ер бусын энгийн байдаг.

Шинэ оператор (дашрамд хэлэхэд 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) эхлүүлнэ.

Бид шалгадаг:

$./memtest
28.5714 GB / s

Өөр нэг зүйл.

Түүхийн ёс суртахуун - хэрэв танд хурдан ажиллахын тулд том буфер хэрэгтэй бол тэдгээрийг эхлүүлэхээ бүү мартаарай.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх