خراب جاچ بابت ٿورو وڌيڪ

هڪ ڏينهن مون اتفاقي طور تي ڪوڊ ۾ آيو ته هڪ صارف پنهنجي ورچوئل مشين ۾ رام ڪارڪردگي جي نگراني ڪرڻ جي ڪوشش ڪري رهيو هو. مان هي ڪوڊ نه ڏيندس (هتي هڪ ”پيٽ ڪپڙو“ آهي) ۽ مان صرف تمام ضروري ڇڏيندس. سو، ٻلي اسٽوڊيو ۾ آهي!

#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.

ڇا؟!؟!

ڪيئن؟!؟!؟

هي آهي Core i7 (جيتوڻيڪ سڀ کان نئون ناهي)، DDR4، پروسيسر لڳ ڀڳ لوڊ نه ڪيو ويو آهي - ڇو؟!؟!

جواب، هميشه وانگر، غير معمولي طور تي عام آهي.

نئون آپريٽر (جهڙوڪ malloc فنڪشن، رستي جي ذريعي) اصل ۾ ميموري مختص نه ڪندو آهي. هن ڪال سان، مختص ڪندڙ ميموري پول ۾ مفت جڳهن جي فهرست کي ڏسي ٿو، ۽ جيڪڏهن ڪو به نه آهي، ڪال ڪري ٿو sbrk() ڊيٽا جي حصي کي وڌائڻ لاءِ، ۽ پوءِ پروگرام ڏانهن واپس اچي ٿو صرف نئين هنڌ کان ايڊريس جو حوالو. مختص ڪيل.

مسئلو اهو آهي ته مختص ٿيل علائقو مڪمل طور تي مجازي آهي. ڪوبه حقيقي ياداشت وارا صفحا مختص نه ڪيا ويا آهن.

۽ جڏهن هن مختص ٿيل حصي مان هر صفحي تائين پهرين رسائي ٿئي ٿي، MMU هڪ صفحي جي غلطي کي "شوٽ" ڪري ٿو، جنهن کان پوء مجازي صفحي تائين رسائي حاصل ڪئي وئي آهي هڪ حقيقي هڪ مقرر ڪيو ويو آهي.

تنهن ڪري، حقيقت ۾، اسان بس ۽ رام ماڊلز جي ڪارڪردگي جي جانچ نه ڪندا آهيون، پر آپريٽنگ سسٽم جي MMU ۽ VMM جي ڪارڪردگي. ۽ رام جي حقيقي ڪارڪردگي کي جانچڻ لاء، اسان کي صرف هڪ ڀيرو مختص ٿيل علائقن کي شروع ڪرڻ جي ضرورت آهي. مثال طور هن طرح:

#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

تبصرو شامل ڪريو