Jika saya menggunakan malloc
, apakah malloc
selalu menggunakan algoritma yang sama terlepas dari apa yang dialokasikan atau apakah itu melihat data dan memilih algoritma appriopriate?
Bisakah kita membuat malloc lebih cepat atau lebih pintar dengan memilih algoritma yang lebih efisien? Dalam pengujian saya, sistem resmi bawaan malloc
Ubuntu adalah 10 kali lebih lambat dari proyek sekolah jika hasil tes saya benar. Apa yang menangkap? Saya terkejut yang malloc
melakukan begitu buruk dalam tes karena itu harus dioptimalkan. Apakah selalu menggunakan algoritma yang sama? Apakah ada implementasi referensi malloc
? Jika saya ingin melihat sumbernya malloc
, yang mana yang harus saya perhatikan? Tes yang saya jalankan adalah sebagai berikut:
/* 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);
}
Apakah tes ini baik-baik saja? Saya juga menggunakan tes ini:
for (i = 0; i < 1000000; i++) {
void *p = malloc(1024 * 1024 * 1024);
free(p);
}
- memperbarui
Menurut komentar, saya harus membuat potongan-potongan berukuran bervariasi dan gratis dalam urutan yang berbeda daripada mengalokasikan, jadi saya mencoba:
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);
}
Maka malloc khusus saya tidak lagi lebih cepat:
$ 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
Algoritma yang saya gunakan adalah:
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
(atau apa pun yang digunakan pengalokasi modern).
calloc
dan kemudian secara eksplisit jelas?
malloc
lebih lambat. Itulah yang saya harapkan.