Nog iets over slechte tests

Op een dag kwam ik per ongeluk code tegen die een gebruiker probeerde de RAM-prestaties in zijn virtuele machine te controleren. Ik zal deze code niet geven (er is daar een ‘voetdoek’) en ik laat alleen het meest essentiële achter. Dus de kat is in de studio!

#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;
}

Het is eenvoudig: wijs geheugen toe en schrijf er één gigabyte in. En wat blijkt uit deze test?

$ ./memtest
4.06504 GB / s

Ongeveer 4 GB/s.

Wat?!?!

Hoe?!?!?

Dit is Core i7 (zij het niet de nieuwste), DDR4, de processor is bijna niet geladen - WAAROM?!?!

Het antwoord is, zoals altijd, buitengewoon gewoon.

De nieuwe operator (zoals trouwens de malloc-functie) wijst feitelijk geen geheugen toe. Met deze aanroep kijkt de allocator naar de lijst met vrije locaties in de geheugenpool, en als die er niet zijn, roept hij sbrk() aan om het datasegment te vergroten, en keert dan terug naar het programma met een verwijzing naar het adres vanaf de nieuwe locatie. toegewezen.

Het probleem is dat het toegewezen gebied volledig virtueel is. Er worden geen echte geheugenpagina's toegewezen.

En wanneer de eerste toegang tot elke pagina vanuit dit toegewezen segment plaatsvindt, “schiet” de MMU een paginafout op, waarna de virtuele pagina die wordt bezocht een echte pagina krijgt toegewezen.

Daarom testen we in feite niet de prestaties van de bus- en RAM-modules, maar de prestaties van de MMU en VMM van het besturingssysteem. En om de echte prestaties van RAM te testen, hoeven we de toegewezen gebieden slechts één keer te initialiseren. Bijvoorbeeld als volgt:

#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;
}

Dat wil zeggen dat we eenvoudigweg de toegewezen buffers initialiseren met de standaardwaarde (char 0).

controleren:

$ ./memtest
28.5714 GB / s

Nog iets.

Moraal - als je grote buffers nodig hebt om snel te werken, vergeet dan niet om ze te initialiseren.

Bron: www.habr.com

Voeg een reactie