Bir kuni men foydalanuvchi virtual mashinasida RAM ishlashini kuzatish uchun ishlatayotgan kodni topdim. Men kodni baham ko'rmayman (bu biroz noqulay) va faqat asosiy narsalarni baham ko'raman. Demak, mushuk studiyada!
#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;
}Hammasi oddiy: xotirani ajrating va unga bir gigabayt yozing. Xo'sh, bu test nimani ko'rsatadi?
$ ./memtest
4.06504 G / s
Taxminan 4 GB/s.
Nima?!?!
Qanaqasiga?!?!?
Bu Core i7 (eng yangisi bo'lmasa ham), DDR4, protsessor deyarli yuklanmagan - NEGA?!?!
Javob, har doimgidek, g'ayrioddiy.
Yangi operator (masalan, malloc funktsiyasi kabi) aslida xotirani ajratmaydi. Chaqirilganda ajratuvchi hovuzdagi bo'sh xotira bloklari ro'yxatini ko'rib chiqadi va agar ular bo'lmasa, ma'lumotlar segmentini oshirish uchun sbrk() ni chaqiradi va keyin yangi ajratilgan blokning manziliga havolani qaytaradi.
Muammo shundaki, ajratilgan maydon butunlay virtualdir. Haqiqiy xotira sahifalari ajratilmagan.
Va ushbu ajratilgan segmentdan har bir sahifaga birinchi marta kirish sodir bo'lganda, MMU sahifa xatosini "yondiradi", shundan so'ng kirilgan virtual sahifaga haqiqiy sahifa tayinlanadi.
Demak, haqiqatda biz shina va operativ xotira modullarining ishlashini emas, balki operatsion tizimning MMU va VMM ishlashini sinab ko‘rmoqdamiz. RAMning haqiqiy ishlashini tekshirish uchun biz ajratilgan maydonlarni bir marta ishga tushirishimiz kerak. Masalan, bu kabi:
#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;
}Ya'ni, biz ajratilgan buferlarni oddiy qiymat bilan ishga tushiramiz (char 0).
Biz tekshiramiz:
$ ./memtest
28.5714 G / s
Bu boshqa masala.
Hikoyaning axloqiy tomoni shundaki, agar sizga tez ishlash uchun katta buferlar kerak bo'lsa, ularni ishga tushirishni unutmang.
Manba: www.habr.com
