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