我剛剛開始使用C,對malloc()
和free()
的性能問題知之甚少。我的問題是這樣的:如果我打電話malloc()
後跟free()
在一個while
循環內循環了20次迭代,它會比調用free()
以外的循環慢嗎?C編程:malloc和循環內部免費
我實際上使用第一種方法來分配內存到緩衝區,從文件中讀取可變長度字符串,執行一些字符串操作,然後在每次迭代後清除緩衝區。如果我的方法導致很多開銷,那麼我想請求一個更好的方法來實現相同的結果。
我剛剛開始使用C,對malloc()
和free()
的性能問題知之甚少。我的問題是這樣的:如果我打電話malloc()
後跟free()
在一個while
循環內循環了20次迭代,它會比調用free()
以外的循環慢嗎?C編程:malloc和循環內部免費
我實際上使用第一種方法來分配內存到緩衝區,從文件中讀取可變長度字符串,執行一些字符串操作,然後在每次迭代後清除緩衝區。如果我的方法導致很多開銷,那麼我想請求一個更好的方法來實現相同的結果。
肯定慢。 (但是,請記住,你需要平衡的malloc
和free
數量,否則你會得到一個內存泄漏。)
如果長度不同,您可以使用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);
+1 - 但你不覺得'bufsize = reqbufsize * 2;'有點激烈嗎? :P –
也許吧。重新分配時,'std :: vector'的MSVC2k8實現增加了150%的緩衝區。 –
@BillyONeal:這實際上是一種很常見的做事情的方式。 – Dinah
如果您知道緩衝區的最大長度 - 或者可以設置合理的最大值 - 那麼您可以爲每次迭代使用相同的緩衝區。否則你在做什麼應該沒問題。
這取決於malloc和free的實現。
來回復您的問題,最好的辦法是建立一個基準...
這取決於你需要的緩衝區。
您是否真的需要在每次迭代後清除它,或者末尾的字符可能足以標記字符串的結尾?畢竟這是各種str
庫調用的用途。
如果您確實需要清除它,您可以使用bzero()
。當然,每次迭代都會出現malloc'ing和free'ing浪費資源,因爲您可以愉快地重新使用緩衝區。
如果要並行化for循環,即使用多個併發線程使用它,則會出現另一個問題。
簡單實際的例子:使用水桶來運送水。假設你需要用那個桶做幾次旅行:它是否有意義拿起來,使用它,放下它,再次拿起它,使用它,等等......?您可以儘可能多次重複使用存儲桶。 另一方面,如果需要您和更多人使用存儲桶,可以組織對存儲桶的訪問或需要更多存儲桶。
最後建議:現在不用擔心表演現在。他們說,早期優化是萬惡之源,你很快就會明白爲什麼。
首先,瞭解問題:編寫可丟棄的代碼。實驗。 其次,測試它。確保它滿足你的需求。 第三,優化它。讓循環運行一萬次並測量需要多長時間。然後將malloc移出外部並再次測量(如果在UNIX下使用shell命令time
)。 第四,重寫它,因爲你的第一個實驗很可能是一堆嘗試重試 - 而不是工作代碼。
沖洗,重複。
ps:同時玩得開心。這應該是有趣的,並不令人沮喪。
一般來說,任何可以在循環外移動的東西都應該是。爲什麼重複同樣的行動,當你只能做一次?
Justin Ethier是正確的,分配一個緩衝區,將舒適地適合最大的字符串和重用。
對於20次迭代,您不應該擔心malloc/free的性能。即使對於更多(幾個數量級)的數據,你也不應該開始考慮優化,直到你剖析代碼並理解什麼是緩慢的。
最後,如果您要釋放緩衝區,則無需先清除緩衝區。即使你要將malloc/free移到循環之外(使用Justin建議的最大緩衝區),也不需要明確清除緩衝區。
如果你調用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);
過程變得更好。有一些僞代碼:
#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);
如果你調用它裏面的malloc不能撥打免費外循環,否則你會泄漏對所有的內存,但是從最後一次迭代的malloc。但是,您可以使用realloc而不是malloc,然後在外面釋放。 – Cascabel
@Jefromi:我認爲你應該讓這個評論成爲一個答案。 –
你的英語很好 - 實際上它比大多數新手的英語都好。 –