2010-03-17 75 views
5

我剛剛開始使用C,對malloc()free()的性能問題知之甚少。我的問題是這樣的:如果我打電話malloc()後跟free()在一個while循環內循環了20次迭代,它會比調用free()以外的循環慢嗎?C編程:malloc和循環內部免費

我實際上使用第一種方法來分配內存到緩衝區,從文件中讀取可變長度字符串,執行一些字符串操作,然後在每次迭代後清除緩衝區。如果我的方法導致很多開銷,那麼我想請求一個更好的方法來實現相同的結果。

+5

如果你調用它裏面的malloc不能撥打免費外循環,否則你會泄漏對所有的內存,但是從最後一次迭代的malloc。但是,您可以使用realloc而不是malloc,然後在外面釋放。 – Cascabel

+0

@Jefromi:我認爲你應該讓這個評論成爲一個答案。 –

+2

你的英語很好 - 實際上它比大多數新手的英語都好。 –

回答

13

肯定慢。 (但是,請記住,你需要平衡的mallocfree數量,否則你會得到一個內存泄漏。)

如果長度不同,您可以使用realloc擴大緩衝區大小。

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 - 但你不覺得'bufsize = reqbufsize * 2;'有點激烈嗎? :P –

+0

也許吧。重新分配時,'std :: vector'的MSVC2k8實現增加了150%的緩衝區。 –

+4

@BillyONeal:這實際上是一種很常見的做事情的方式。 – Dinah

3

如果您知道緩衝區的最大長度 - 或者可以設置合理的最大值 - 那麼您可以爲每次迭代使用相同的緩衝區。否則你在做什麼應該沒問題。

0

這取決於malloc和free的實現。

來回復您的問題,最好的辦法是建立一個基準...

1

這取決於你需要的緩衝區。

您是否真的需要在每次迭代後清除它,或者末尾的字符可能足以標記字符串的結尾?畢竟這是各種str庫調用的用途。

如果您確實需要清除它,您可以使用bzero()。當然,每次迭代都會出現malloc'ing和free'ing浪費資源,因爲您可以愉快地重新使用緩衝區。

如果要並行化for循環,即使用多個併發線程使用它,則會出現另一個問題。

簡單實際的例子:使用水桶來運送水。假設你需要用那個桶做幾次旅行:它是否有意義拿起來,使用它,放下它,再次拿起它,使用它,等等......?您可以儘可能多次重複使用存儲桶。 另一方面,如果需要您和更多人使用存儲桶,可以組織對存儲桶的訪問或需要更多存儲桶。

最後建議:現在不用擔心表演現在。他們說,早期優化是萬惡之源,你很快就會明白爲什麼。

首先,瞭解問題:編寫可丟棄的代碼。實驗。 其次,測試它。確保它滿足你的需求。 第三,優化它。讓循環運行一萬次並測量需要多長時間。然後將malloc移出外部並再次測量(如果在UNIX下使用shell命令time)。 第四,重寫它,因爲你的第一個實驗很可能是一堆嘗試重試 - 而不是工作代碼。

沖洗,重複。

ps:同時玩得開心。這應該是有趣的,並不令人沮喪。

1

一般來說,任何可以在循環外移動的東西都應該是。爲什麼重複同樣的行動,當你只能做一次?

Justin Ethier是正確的,分配一個緩衝區,將舒適地適合最大的字符串和重用。

6

對於20次迭代,您不應該擔心malloc/free的性能。即使對於更多(幾個數量級)的數據,你也不應該開始考慮優化,直到你剖析代碼並理解什麼是緩慢的。

最後,如果您要釋放緩衝區,則無需先清除緩衝區。即使你要將malloc/free移到循環之外(使用Justin建議的最大緩衝區),也不需要明確清除緩衝區。

6

如果你調用malloc裏面你不能在循環外撥打免費電話:

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

,你將有malloc分配num_files次,但只釋放一次 - 你從所有泄漏的內存,但最後!

主要有兩種選擇 - 循環之前的malloc(或只使用一個數組)如果你知道一個大小,將一切工作,或使用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

過程變得更好。有一些僞代碼:

#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);