د خرابې ازموینې په اړه یو څه نور

یوه ورځ زه په ناڅاپي ډول د کوډ سره مخ شوم چې یو کارن هڅه کوي په خپل مجازی ماشین کې د رام فعالیت څارنه وکړي. زه به دا کوډ نه ورکوم (دلته "پښې جامې" شتون لري) او زه به یوازې خورا اړین پریږدم. نو، پیشو په سټوډیو کې ده!

#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

نږدې 4GB/s.

څه؟!؟!

هغه څنګه؟!؟!؟

دا کور 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;
}

دا دی ، موږ په ساده ډول تخصیص شوي بفرونه د ډیفالټ ارزښت (چار 0) سره پیل کوو.

موږ ګورو:

$ ./memtest
28.5714 GB / s

بل شی.

د کیسې اخلاقي - که تاسو د ګړندي کار کولو لپاره لوی بفرونو ته اړتیا لرئ ، نو د دوی پیل کول مه هیروئ.

سرچینه: www.habr.com

Add a comment