ስለ መጥፎ ሙከራ ትንሽ ተጨማሪ

አንድ ቀን ተጠቃሚው በቨርቹዋል ማሽኑ ውስጥ ያለውን የ 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 ጊባ / ሰ

በግምት 4GB/s

ምንድን?!?!

እንዴት?!?!?

ይህ Core i7 ነው (ምንም እንኳን አዲሱ ባይሆንም)፣ DDR4፣ ፕሮሰሰሩ አልተጫነም ማለት ይቻላል - ለምን?!?!

መልሱ, እንደ ሁልጊዜ, ያልተለመደ ተራ ነው.

አዲሱ ኦፕሬተር (እንደ malloc ተግባር, በነገራችን ላይ) ማህደረ ትውስታን በትክክል አይመድብም. በዚህ ጥሪ, አከፋፋዩ በማስታወሻ ገንዳ ውስጥ ያሉትን ነፃ ቦታዎች ዝርዝር ይመለከታል, እና ምንም ከሌለ, የውሂብ ክፍሉን ለመጨመር sbrk () ይደውሉ እና ከዚያ ወደ ፕሮግራሙ አድራሻውን ከአዲሱ ቦታ ማጣቀሻ ይመልሳል. ተመድቧል።

ችግሩ የተመደበው ቦታ ሙሉ በሙሉ ምናባዊ ነው. ምንም እውነተኛ የማስታወሻ ገጾች አልተመደቡም።

እና ከዚህ ከተመደበው ክፍል ወደ እያንዳንዱ ገጽ የመጀመሪያ መዳረሻ ሲከሰት ኤምኤምዩ የአንድ ገጽ ስህተት “ይተኩሳል”፣ ከዚያ በኋላ የሚደረስበት ምናባዊ ገጽ እውነተኛ ይመደባል።

ስለዚህ፣ በእውነቱ፣ የአውቶቡስ እና ራም ሞጁሎችን አፈጻጸም እየሞከርን አይደለም፣ ነገር ግን የስርዓተ ክወናው 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 ጊባ / ሰ

ሌላው ነገር.

የታሪኩ ሞራል - በፍጥነት ለመስራት ትላልቅ ማገጃዎች ከፈለጉ እነሱን ማስጀመርዎን አይርሱ።

ምንጭ: hab.com

አስተያየት ያክሉ