చెడు పరీక్ష గురించి కొంచెం ఎక్కువ

ఒక రోజు నేను అనుకోకుండా ఒక వినియోగదారు తన వర్చువల్ మెషీన్‌లో 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
X GB 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
X GB GB / s

వేరె విషయం.

కథ యొక్క నైతికత - త్వరగా పని చేయడానికి మీకు పెద్ద బఫర్‌లు అవసరమైతే, వాటిని ప్రారంభించడం మర్చిపోవద్దు.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి