Wenn ich verwende malloc
, wird malloc
immer derselbe Algorithmus verwendet, unabhängig davon, was zugewiesen wird, oder werden die Daten überprüft und ein geeigneter Algorithmus ausgewählt?
Können wir Malloc schneller oder intelligenter machen, indem wir einen effizienteren Algorithmus wählen? In meinen Tests ist das eingebaute offizielle System malloc
von Ubuntu zehnmal langsamer als ein Schulprojekt, wenn meine Testergebnisse korrekt sind. Was ist der Haken? Ich bin überrascht, dass malloc
die Tests so schlecht abschnitten, weil sie optimiert werden sollten. Verwendet es immer den gleichen Algorithmus? Gibt es eine Referenzimplementierung von malloc
? Wenn ich nach der Quelle suchen möchte, nach malloc
welcher sollte ich suchen? Die Tests, die ich durchführe, sind die folgenden:
/* returns an array of arrays of char*, all of which NULL */
char ***alloc_matrix(unsigned rows, unsigned columns) {
char ***matrix = malloc(rows * sizeof(char **));
unsigned row = 0;
unsigned column = 0;
if (!matrix) abort();
for (row = 0; row < rows; row++) {
matrix[row] = calloc(columns, sizeof(char *));
if (!matrix[row]) abort();
for (column = 0; column < columns; column++) {
matrix[row][column] = NULL;
}
}
return matrix;
}
/* deallocates an array of arrays of char*, calling free() on each */
void free_matrix(char ***matrix, unsigned rows, unsigned columns) {
unsigned row = 0;
unsigned column = 0;
for (row = 0; row < rows; row++) {
for (column = 0; column < columns; column++) {
/* printf("column %d row %d\n", column, row);*/
free(matrix[row][column]);
}
free(matrix[row]);
}
free(matrix);
}
int main(int agrc, char **argv) {
int x = 10000;
char *** matrix = alloc_matrix(x, x);
free_matrix(matrix, x, x);
return (0);
}
Ist der Test in Ordnung? Ich benutze auch diesen Test:
for (i = 0; i < 1000000; i++) {
void *p = malloc(1024 * 1024 * 1024);
free(p);
}
- aktualisieren
Dem Kommentar zufolge sollte ich Stücke mit variabler Größe erstellen und in einer anderen Reihenfolge als der Zuweisung freigeben. Deshalb versuche ich:
int main(int agrc, char **argv) {
int i;
srand(time(NULL));
int randomnumber;
int size = 1024;
void *p[size];
for (i = 0; i < size; i++) {
randomnumber = rand() % 10;
p[i] = malloc(1024 * 1024 * randomnumber);
}
for (i = size-1; i >= 0; i--) {
free(p[i]);
}
int x = 1024;
char *** matrix = alloc_matrix(x, x);
free_matrix(matrix, x, x);
return (0);
}
Dann ist mein benutzerdefiniertes Malloc nicht mehr schneller:
$ time ./gb_quickfit
real 0m0.154s
user 0m0.008s
sys 0m0.144s
dac@dac-Latitude-E7450:~/ClionProjects/omalloc/openmalloc/overhead$ time ./a.out
real 0m0.014s
user 0m0.008s
sys 0m0.004s
Der von mir verwendete Algorithmus war:
void *malloc_quick(size_t nbytes) {
Header *moreroce(unsigned);
int index, i;
index = qindex(nbytes);
/*
* Use another strategy for too large allocations. We want the allocation
* to be quick, so use malloc_first().
*/
if (index >= NRQUICKLISTS) {
return malloc_first(nbytes);
}
/* Initialize the quick fit lists if this is the first run. */
if (first_run) {
for (i = 0; i < NRQUICKLISTS; ++i) {
quick_fit_lists[i] = NULL;
}
first_run = false;
}
/*
* If the quick fit list pointer is NULL, then there are no free memory
* blocks present, so we will have to create some before continuing.
*/
if (quick_fit_lists[index] == NULL) {
Header* new_quick_fit_list = init_quick_fit_list(index);
if (new_quick_fit_list == NULL) {
return NULL;
} else {
quick_fit_lists[index] = new_quick_fit_list;
}
}
/*
* Now that we know there is at least one free quick fit memory block,
* let's use return that and also update the quick fit list pointer so that
* it points to the next in the list.
*/
void* pointer_to_return = (void *)(quick_fit_lists[index] + 1);
quick_fit_lists[index] = quick_fit_lists[index]->s.ptr;
/* printf("Time taken %d seconds %d milliseconds", msec/1000, msec%1000);*/
return pointer_to_return;
}
sbrk
(oder was auch immer moderne Allokatoren verwenden) zahlen müssen .
calloc
und dann explizit klar?
malloc
langsamer ist. Das würde ich erwarten.