2010-03-17 37 views
5

Tôi vừa mới bắt đầu với C và có rất ít kiến ​​thức về các vấn đề về hiệu suất với malloc()free(). Câu hỏi của tôi là: nếu tôi được gọi malloc(), theo sau là free() bên trong vòng lặp while lặp lại 20 vòng lặp, nó sẽ chạy chậm hơn so với gọi số free()bên ngoài vòng lặp? Tôi thực sự đang sử dụng phương pháp đầu tiên để cấp phát bộ nhớ cho một bộ đệm, đọc một chuỗi có độ dài biến đổi từ một tệp, thực hiện một số thao tác chuỗi và sau đó xóa bộ đệm sau mỗi lần lặp lại. Nếu phương pháp của tôi dẫn đến rất nhiều chi phí thì tôi muốn yêu cầu một cách tốt hơn để tôi đạt được kết quả tương tự.Lập trình C: malloc và miễn phí trong vòng một

+5

Bạn không thể gọi miễn phí bên ngoài vòng lặp nếu bạn đang gọi malloc bên trong nó hoặc bạn sẽ tiết lộ bộ nhớ cho tất cả trừ malloc từ lần lặp cuối cùng. Bạn có thể, tuy nhiên, sử dụng realloc thay vì malloc, sau đó miễn phí bên ngoài. – Cascabel

+0

@ Jefromi: Tôi nghĩ bạn nên đưa ra nhận xét đó một câu trả lời. –

+2

Tiếng Anh của bạn là tốt - nó tốt hơn trong thực tế hơn so với hầu hết người mới của tiếng Anh trên SO. –

Trả lời

13

Chắc chắn chậm hơn. (Nhưng hãy nhớ rằng bạn cần cân bằng số lượng mallocfree nếu không bạn bị rò rỉ bộ nhớ.)

Nếu chiều dài thay đổi, bạn có thể sử dụng realloc để mở rộng kích thước bộ đệm.

void* v = malloc(1024); 
size_t bufsize = 1024; 

while(cond) { 
    size_t reqbufsize = get_length(); 
    if (reqbufsize > bufsize) { 
     bufsize = reqbufsize * 2; 
     v = realloc(v, bufsize); 
    } 
    // you may shrink it also. 

    do_something_with_buffer(v); 
} 

free(v); 
+2

+1 - nhưng bạn không nghĩ rằng 'bufsize = reqbufsize * 2;' là một chút quyết liệt? : P –

+0

Có thể. Việc thực thi MSVC2k8 của 'std :: vector' tăng bộ đệm của nó lên 150% khi tái phân bổ. –

+4

@ BillyONeal: Đó thực sự là một cách khá phổ biến để làm mọi thứ. – Dinah

3

Nếu bạn biết độ dài tối đa của bộ đệm - hoặc có thể đặt mức tối đa hợp lý - thì bạn có thể sử dụng cùng một bộ đệm cho mỗi lần lặp lại. Nếu không những gì bạn đang làm sẽ ổn thôi.

0

Nó phụ thuộc vào việc triển khai malloc và miễn phí.

Cách tốt nhất để trả lời câu hỏi của bạn là tạo điểm chuẩn ...

1

Tùy thuộc vào những gì bạn cần bộ đệm.

Bạn có thực sự cần phải xóa nó sau mỗi lần lặp lại hoặc có thể là \0 char ở cuối sẽ đủ để đánh dấu sự kết thúc của một chuỗi? Sau khi tất cả những gì mà các cuộc gọi thư viện str khác nhau sử dụng.

Nếu bạn thực sự cần xóa nó, bạn có thể sử dụng bzero(). Chắc chắn malloc'ing và free'ing tại mỗi iteration là một sự lãng phí tài nguyên, vì bạn hạnh phúc có thể tái sử dụng bộ đệm.

Một vấn đề khác sẽ phát sinh nếu bạn song song vòng lặp for, tức là có một số luồng đồng thời sử dụng nó.

Ví dụ đơn giản, thực tế: sử dụng xô để mang nước. Giả sử bạn cần thực hiện một số chuyến đi với nhóm đó: bạn có muốn nhặt nó lên, sử dụng nó, đặt nó xuống, nhặt nó lên lần nữa, sử dụng nó, v.v ...? Bạn có thể tái sử dụng thùng nhiều lần nhất có thể. Nếu, mặt khác, nhóm cần phải được bạn và nhiều người sử dụng, hoặc bạn tổ chức truy cập vào thùng hoặc cần nhiều nhóm hơn.

Đề xuất cuối cùng: đừng lo lắng về buổi biểu diễn ngay bây giờ. Họ nói rằng tối ưu hóa sớm là gốc rễ của tất cả các điều ác, và bạn sẽ sớm hiểu tại sao.

Thứ nhất, hãy hiểu vấn đề: viết mã có thể bị vứt bỏ. Thí nghiệm. Thứ hai, kiểm tra nó. Hãy chắc chắn rằng nó làm những gì bạn cần. Thứ ba, tối ưu hóa nó. Làm cho vòng lặp chạy mười nghìn lần và đo thời gian cần thiết. Sau đó di chuyển malloc bên ngoài, và đo lại (sử dụng lệnh shell time nếu theo UNIX). Thứ tư, viết lại nó bởi vì thử nghiệm đầu tiên của bạn rất có thể sẽ là một mớ hỗn độn của các bản thử lại không hoạt động.

Rửa sạch, lặp lại.

ps: vui chơi trong thời gian trung bình. Nó được cho là thú vị, không bực bội.

1

Thường thì mọi thứ có thể di chuyển ra ngoài vòng lặp phải là. Tại sao lặp lại cùng một hành động khi bạn chỉ có thể làm điều đó một lần?

Justin Ethier là đúng, phân bổ bộ đệm phù hợp thoải mái với chuỗi lớn nhất và tái sử dụng.

6

Trong 20 lần lặp lại, bạn không nên lo lắng về hiệu suất của malloc/miễn phí.

Thậm chí đối với nhiều thứ hơn (một vài đơn vị độ lớn), bạn không nên bắt đầu suy nghĩ về tối ưu hóa cho đến khi bạn cấu hình mã và hiểu những gì đang chậm.

Cuối cùng, nếu bạn định giải phóng bộ đệm, không cần phải xóa bộ đệm trước. Ngay cả khi bạn đã di chuyển malloc/miễn phí bên ngoài vòng lặp (sử dụng bộ đệm tối đa theo đề xuất của Justin), bạn không cần phải xóa bộ đệm một cách rõ ràng.

6

Bạn không thể gọi miễn phí bên ngoài vòng lặp nếu bạn đang gọi malloc bên:

char * buffer; 
for (int i = 0; i < num_files; i++) { 
    buffer = malloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 

Bạn sẽ malloc'ed num_files lần, nhưng chỉ giải phóng một lần - bạn bị rò rỉ bộ nhớ từ khắp nơi nhưng cuối cùng !

Có hai lựa chọn chính - malloc trước khi vòng lặp (hoặc chỉ cần sử dụng một mảng) nếu bạn biết một kích thước mà sẽ làm việc cho tất cả mọi thứ, hoặc sử dụng realloc:

char * buffer = NULL; 
for (int i = 0; i < num_files; i++) { 
    buffer = realloc(proper_length(i)); 
    // do some things with buffer 
} 
free(buffer); 
0

Process nó tốt hơn. Có một số mã giả:

#define BLOCK_SIZE 1024 // or about the bigger size of your strings. 

char *buffer = (char *) malloc(BLOCK_SIZE) 

for(int i=0; i<20; i++) 
{ 
    while (more bytes left to read) 
    { 
    read full string or BLOCK_SIZE bytes at max // most calls work this way 
    proces bytes in buffer 
    } 
} 

free(buffer); 
Các vấn đề liên quan