Nếu tôi sử dụng malloc
, malloc
luôn luôn sử dụng cùng một thuật toán bất kể nó được phân bổ hay nó nhìn vào dữ liệu và chọn một thuật toán phù hợp?
Chúng ta có thể làm cho malloc nhanh hơn hoặc thông minh hơn bằng cách chọn một thuật toán hiệu quả hơn không? Trong các thử nghiệm của tôi, hệ thống chính thức dựng sẵn malloc
của Ubuntu chậm hơn 10 lần so với dự án trường học nếu kết quả kiểm tra của tôi là chính xác. Nắm bắt được những gì? Tôi ngạc nhiên khi malloc
thực hiện quá tệ trong các bài kiểm tra vì nó phải được tối ưu hóa. Có phải nó luôn luôn sử dụng cùng một thuật toán? Có một tham chiếu thực hiện malloc
? Nếu tôi muốn xem nguồn malloc
, tôi nên xem cái nào? Các bài kiểm tra tôi chạy như sau:
/* 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);
}
Bài kiểm tra có ổn không? Tôi cũng sử dụng thử nghiệm này:
for (i = 0; i < 1000000; i++) {
void *p = malloc(1024 * 1024 * 1024);
free(p);
}
- cập nhật
Theo nhận xét, tôi nên tạo các khối có kích thước thay đổi và miễn phí theo thứ tự khác với phân bổ, vì vậy tôi thử:
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);
}
Sau đó, malloc tùy chỉnh của tôi không còn nhanh hơn:
$ 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
Thuật toán tôi sử dụng là:
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
(hoặc bất kỳ phân bổ hiện đại nào sử dụng).
calloc
và sau đó rõ ràng rõ ràng?
malloc
chậm hơn. Đó là những gì tôi mong đợi.