2011-09-30 61 views
14

我發送一個文本文件 - 客戶端服務器 將文本分解成每個512字節的數據包 但某些數據包包含的文本小於最大大小,因此在服務器端接收每個數據包時我調用malloc()再次建立一個字符串,這是一個不好的做法? 保持一個可以適應最大長度的工作緩衝區並保持迭代,複製和覆蓋它的值會更好嗎?繼續調用malloc()和free()會有多糟糕?

好的@n.m。這裏是代碼,這個如果是在一個for(;;)循環內被select()喚醒()

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

一行代碼值得一千個評論。 –

+0

@ n.m。我將代碼添加到主帖 – cap10ibrahim

回答

11

在你的例子中,你的函數已經包含一個系統調用,所以malloc/free的相對成本幾乎不可測量。在我的系統上,「往返」平均約爲300個週期,並且系統調用(獲取當前時間,pid等)至少需要2500個週期。預計recv很容易花費10倍,在這種情況下,分配/釋放內存的成本至多約爲該操作總成本的1%。

當然,確切的時間安排會有所不同,但粗略的數量級在整個系統中應該是相當不變的。我甚至不會考慮刪除malloc/free作爲優化,除非是純粹是用戶空間的函數。在沒有動態分配的情況下,可能實際上更有價值的是在不應該出現失敗情況的操作中 - 這裏的值是您簡化了加固您可以不必擔心當malloc失敗時該怎麼辦。

+0

我覺得很難相信你的malloc/free只需要300個週期。你是否正在使用一個碎片堆,並且包含需要從操作系統中引入新內存並釋放它的malloc? –

+1

我正在計算'free(malloc(1));'(在Linux/glibc/i686上,使用'rdtsc'測量)何時不需要從操作系統映射新內存,只需重新使用先前釋放的內存。這幾乎總是常見的情況。您只需要擔心從操作系統獲得新內存的時間就是實時編程,您可以關心任何操作的**最差情況**延遲,而不是程序的整體運行時間。 –

+3

使用初始化爲NULL的隨機大小的malloc/free隨機分配插槽的10-100個分配數組將是更好的測試。 –

1

只有測試可以告訴。當用C語言編程時,我儘量避免使用malloc,因爲如果你偶然創建一個內存泄漏可能很難解決。

7

與調用malloc和free相關的開銷。一個塊必須從堆中分配,並在使用時標記爲已使用,當你釋放出現時。不知道你正在使用的操作系統或編譯器,這可能在c庫或OS內存管理級別。由於你正在做很多malloc和釋放,你可以在你的堆沒有足夠的連續空閒內存的地方使用malloc來分割你的堆。如果您只能分配一個緩衝區並繼續使用它,那通常會更快,並且堆碎片的危險更小。

+2

如果他一遍又一遍地分配和釋放一個固定大小的塊,他幾乎肯定不會分解任何東西。 (這並不意味着沒有開銷......但在這種情況下,碎片可能不是原因。) – Nemo

+0

假設沒有別的從程序堆中分配內存,並且它是單線程的,我同意。它可能每次都返回相同的內存塊。但是,我們不知道程序中還有哪些內容是從堆中分配的,或者如何實現這個特定的堆管理器。 – user957902

3

我發現malloc,realloc和free很貴。如果你可以避免malloc,最好重用你已經擁有的內存。

編輯:
它看起來像我錯了多少昂貴的malloc是。在Linux上使用GNU C庫版本2.14一些時間測試顯示,該循環10萬次分配和釋放512個插槽與1個隨機大小,以163840個字節的測試:

tsc average loop = 408 
tsc of longest loop = 294350 

所以浪費了408個循環做malloc或在一個緊密的內部循環中做new將是一件愚蠢的事情。除此之外,別擔心這一點。

+0

感謝您的反饋 – cap10ibrahim

1

衡量兩種解決方案的性能。通過分析或測量吞吐量。確實無法說出任何事情。