Еще немного о неправильном тестировании
Однажды мне случайно попался на глаза код, которым пользователь пытался мониторить производительность RAM в своей виртуальной машине. Код этот я приводить не буду (там «портянка») и оставлю только самое существенное. Итак, кот в студии!
#include
#include
#include
#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
Всё просто — выделяем память и пишем в неё один гигабайт. И что показывает этот тест?
$ ./memtest
4.06504 GB/s
Примерно 4GB/s.
Что??!!
Как??!?!
Это Core i7 (пусть и не самый новый), DDR4, процессор почти не загружен — ПОЧЕМУ??!!
Ответ, как всегда, необыкновенно обыкновенный.
Оператор new (как и функция malloc, кстати) на самом деле не выделяет память. При этом вызове аллокатор смотрит список свободных участков в пуле памяти, и если их нет, вызывает sbrk () чтобы увеличить сегмент данных, и затем возвращает программе ссылку на адрес из нового только что выделенного участка.
Проблема в том, что выделенный участок целиком виртуальный. Реальные страницы памяти не выделены.
И когда происходит первое обращение к каждой странице из этого выделенного сегмента, MMU «выстреливает» page fault, после чего виртуальной странице, к которой производится доступа, назначается реальная.
Поэтому на самом деле мы тестируем не производительность шины и модулей RAM, а производительность MMU и VMM операционной системы. А для того, чтобы тестировать реальную производительность оперативной памяти, нам нужно просто однократно инициализировать выделенные участки. Например так:
#include
#include
#include
#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
То есть, мы просто инициализируем выделяемые буферы значением по умолчанию (char 0).
Проверяем:
$ ./memtest
28.5714 GB/s
Другое дело.
Мораль — если вам нужны большие буферы чтобы быстро-быстро работать, не забывайте их инициализировать.