2011-09-30 32 views
14

Tôi đang gửi tệp văn bản - máy khách-máy chủ chia nhỏ văn bản thành các gói 512 byte nhưng một số gói chứa văn bản nhỏ hơn kích thước tối đa ở phía máy chủ khi nhận được mỗi gói tôi gọi malloc() xây dựng một chuỗi một lần nữa, đây có phải là một thực tế xấu? tốt hơn là giữ một bộ đệm hoạt động có thể phù hợp với độ dài tối đa và tiếp tục lặp lại, sao chép và ghi đè các giá trị của nó?Làm thế nào xấu nó là để giữ gọi malloc() và miễn phí()?

okay @ n.m. đây là mã, điều này nếu nằm trong vòng lặp for (;;) được chọn bởi()

if(nbytes==2) { 
      packet_size=unpack_short(short_buf); 
      printf("packet size is %d\n",packet_size); 
      receive_packet(i,packet_size,&buffer); 
      printf("packet=%s\n",buffer); 
      free(buffer); 
} 
//and here is receive_packet() function 
int receive_packet(int fd,int p_len,char **string) { 
*string = (char *)malloc(p_len-2); // 2 bytes for saving the length  
char *i=*string; 
int temp; 
int total=0; 
int remaining=p_len-2; 
while(remaining>0) { 
    //printf("remaining=%d\n",remaining); 
    temp = recv(fd,*string,remaining,0); 
    total+=temp; 
    remaining=(p_len-2)-total; 
    (*string) += temp; 
} 
*string=i; 
return 0; 
} 
+0

Một dòng mã trị giá một nghìn nhận xét. –

+0

@ n.m. Tôi đã thêm mã vào bài đăng chính – cap10ibrahim

Trả lời

11

Trong ví dụ của bạn, hàm của bạn đã có syscall, vì vậy chi phí tương đối của malloc/free sẽ hầu như không thể thực hiện được. Trên hệ thống của tôi, malloc/free "chuyến đi khứ hồi" trung bình khoảng 300 chu kỳ và giá rẻ nhất syscalls (nhận thời gian hiện tại, pid, v.v.) có giá ít nhất 2500 chu kỳ. Mong đợi recv dễ dàng tốn 10 lần nhiều, trong trường hợp đó chi phí phân bổ/giải phóng bộ nhớ sẽ chiếm tối đa khoảng 1% tổng chi phí của hoạt động này.

Tất nhiên thời gian chính xác sẽ khác nhau, nhưng các đơn đặt hàng thô về độ lớn phải là khá bất biến trên các hệ thống.Tôi thậm chí sẽ không xem xét việc xóa malloc/free làm tối ưu hóa ngoại trừ các chức năng hoàn toàn là không gian người dùng. Trường hợp có thể thực sự có giá trị hơn nếu không có phân bổ động là trong các hoạt động không được có trường hợp lỗi - ở đây giá trị là bạn đơn giản hóaharden bạn mã bằng cách không phải lo lắng về việc phải làm gì khi malloc không thành công.

+0

Tôi thấy khó mà tin rằng malloc của bạn/miễn phí chỉ mất 300 chu kỳ. Bạn đang sử dụng một đống phân mảnh và bao gồm cả mallocs mà cần phải mang lại trong bộ nhớ mới từ hệ điều hành và giải phóng mà phát hành nó? –

+1

Tôi đang định thời gian 'free (malloc (1));' (trên Linux/glibc/i686, đo bằng 'rdtsc') khi nó không cần ánh xạ bộ nhớ mới từ hệ điều hành, chỉ cần sử dụng lại bộ nhớ đã giải phóng trước đó. Điều này hầu như luôn luôn là trường hợp phổ biến. Thời gian duy nhất bạn nên lo lắng về thời gian để có được bộ nhớ mới từ hệ điều hành là trong lập trình thời gian thực, nơi bạn quan tâm đến độ trễ ** tồi tệ nhất ** của bất kỳ hoạt động nào hơn là thời gian chạy tổng thể của chương trình của bạn. –

+3

Nó sẽ là một thử nghiệm tốt hơn để sử dụng một mảng phân bổ 10-100 được khởi tạo cho các vị trí phân bổ ngẫu nhiên NULL và malloc/miễn phí. –

1

Chỉ thử nghiệm mới có thể biết. Khi lập trình trong C tôi làm sai ở phía bên của tránh malloc mặc dù, vì rò rỉ bộ nhớ có thể được khá khó khăn để sửa chữa nếu bạn tạo ra một cách tình cờ.

7

Có chi phí liên quan đến gọi điện thoại miễn phí và miễn phí. Một khối phải được phân bổ từ đống và được đánh dấu là đang sử dụng, khi bạn giải phóng vòng quay lại xảy ra. Không biết bạn đang sử dụng hệ điều hành hoặc trình duyệt nào, điều này có thể nằm trong thư viện c hoặc ở cấp quản lý bộ nhớ OS. Kể từ khi bạn đang làm rất nhiều mallocs và giải phóng bạn có thể gió lên fragmenting fragmenting heap của bạn, nơi bạn có thể không có đủ bộ nhớ miễn phí liền kề để làm một malloc ở nơi khác. Nếu bạn có thể phân bổ chỉ một bộ đệm và tiếp tục sử dụng lại nó, điều đó thường sẽ nhanh hơn và có ít nguy cơ phân mảnh heap hơn.

+2

Nếu anh ta đang phân bổ và giải phóng một khối có kích thước cố định nhiều lần, anh ta gần như chắc chắn không phân mảnh bất cứ thứ gì. (Điều đó không có nghĩa là không có chi phí ... Nhưng phân mảnh có lẽ không phải là nguyên nhân gây ra nó trong trường hợp này.) – Nemo

+0

Giả sử không có gì khác là cấp phát bộ nhớ từ heap trong chương trình, và nó là đơn luồng, tôi đồng ý. Nó có thể là cùng một khối bộ nhớ được trả lại mỗi lần. Tuy nhiên, chúng tôi không có ý tưởng gì khác trong chương trình được phân bổ từ heap, hoặc cách quản lý heap đặc biệt này được thực hiện. – user957902

1

Calling nhiều malloc/free thực sự có thể làm tăng bộ nhớ sử dụng bởi quá trình của bạn (không có bất kỳ rò rỉ liên quan), nếu kích thước truyền cho malloc là biến, như đã được chứng minh bởi câu hỏi này:

C program memory usage - more memory reported than allocated

Vì vậy, phương pháp đệm đơn có lẽ là tốt nhất.

3

Tôi thấy rằng malloc, realloc và miễn phí khá đắt. Nếu bạn có thể tránh malloc nó là tốt hơn để tái sử dụng bộ nhớ mà bạn đã có.

Chỉnh sửa:
Có vẻ như tôi sai về cách malloc đắt tiền. Một số xét nghiệm thời gian với các phiên bản Thư viện GNU C 2.14 trên Linux cho rằng đối với một bài kiểm tra đó vòng 100.000 lần và giao đất và giải phóng 512 khe với kích thước ngẫu nhiên 1-163.840 byte:

tsc average loop = 408 
tsc of longest loop = 294350 

Vì vậy, lãng phí 408 chu kỳ làm malloc hoặc new trong một vòng lặp chặt chẽ bên trong sẽ là một điều ngớ ngẩn để làm. Khác hơn là không lo lắng về nó.

+0

cảm ơn thông tin phản hồi của bạn – cap10ibrahim

1

Đo hiệu suất của hai giải pháp. Hoặc bằng cách lược tả hoặc đo lường thông lượng. Không thể nói bất cứ điều gì chắc chắn.

Các vấn đề liên quan