2015-02-07 47 views
1
void * thread_client_timeout_check(void *arg) 
{ 
    pthread_attr_t attr;size_t size; 
    pthread_attr_init(&attr); 
    pthread_attr_getstacksize(&attr, &size); 
    printf("pthread stacksize: %d\n", size); 
    malloc(1); 
} 

主線程創建子線程並暫停。malloc在子線程中花費太多虛擬內存

int main() 
{ 
    pthread_t pid; 
    pthread_create(&pid, NULL, thread_client_timeout_check, NULL); 
    pause(); 
} 
  1. pthread_create之前,top virtpthread_create0.3m
  2. 後,top virt8.3m(並行線程堆棧大小是8M)
  3. malloc(1)後,top virt72.3m

爲什麼malloc(1)將從內核獲得54m虛擬內存?

+0

並沒有其他線程做任何可能增加內存的東西嗎? – 2015-02-07 09:28:22

+1

如果malloc一直下到每個分配的內核,它會很慢。獲得大塊,然後在用戶空間中處理它們更有意義。 – Mat 2015-02-07 09:48:52

+0

@ Mat你說得對,但54米太大了。我首先在主線程中檢查'malloc(1)',虛擬內存仍然是0.3m。 – 2015-02-07 09:56:35

回答

4

在多線程程序中,glibc 2.10+創建了許多malloc池以減少錯誤共享,從而提高可伸縮性。結果是,從glibc 2.10開始,虛擬內存使用率將會更高。但是,由於地址空間很便宜,或者在64位體系結構上或多或少都是免費的,所以沒什麼可擔心的。

https://udrepper.livejournal.com/20948.html

2

虛擬內存(virt)不是由程序分配的內存。它類似於一種內存腳印(包含數據+代碼+駐留+交換內存,還包含共享庫使用的共享代碼和數據段)。內存分配針對不同的塊大小(fastbins,mmap(),sbrk())使用不同的策略,而小的實際內存使用量可能會導致巨大的virt內存。例如。分配10次64 KiB + 1KiB塊並釋放較低的10 x 64KiB塊。實際使用1 KiB,但堆中的內存數量爲641 KiB(+ cca 100 KiB,用於最高層(所謂的荒野)塊,因爲堆上釋放的內存仍屬於進程的地址空間。

您可以使用mallinfo(3)看到實際可用內存:

#include <malloc.h> 

#define pfld(fld, unit, rem) printf(" %-9s= %d %s, (%s)\n", #fld, mi.fld, #unit, rem) 

void showmem(const char *fnc, const char *step) { 
    struct mallinfo mi = mallinfo(); 

    printf("\n==== %s: %s ====\n", fnc, step); 

    pfld(arena, bytes, "Non-mmapped space allocated"); 
    pfld(ordblks, pcs, "free chunks"); 
    pfld(smblks, pcs, "free fastbin blocks"); 
    pfld(hblks, pcs, "mmapped regions"); 
    pfld(hblkhd, bytes, "Space allocated in mmapped regions"); 
    pfld(usmblks, bytes, "Maximum total allocated space"); 
    pfld(fsmblks, bytes, "Space in freed fastbin blocks"); 
    pfld(uordblks, bytes, "Total allocated space"); 
    pfld(fordblks, bytes, "Total free space"); 
    pfld(keepcost, bytes, "Top-most, releasable space"); 
} 

從調用程序的不同部分這一功能showmem(__FUNCTION__, "Step")你可以看到總分配的空間和可用空間總量。我假設在你的情況下,總可用空間很高,總分配空間很低。這可能是由於pthread庫分配和釋放的內存。

您可以進行測試。使用mallopt(3)你可以要求malloc總是使用mmap(2)來分配內存不是更方便sbrk(2)。通常,mmap(2)僅用於大於或等於128 KiB的塊。當內核提供的malloc'd(導致處理開銷並始終分配4KiB頁)時,Mmap的內存總是爲零,並且在free之後總是從進程的地址空間中移除並返回給內核(所以從free'd指針讀取導致分段錯誤)。如果mmap內存被釋放,它會立即從您的地址空間中移除,因此分配的內存足跡將立即減少。試試:malloc 10 x 128 KiB + 1 KiB,然後釋放10 x 128 KiB。 Virt將被減少爲只包含1 KiB部分。

調用

mallopt(M_MMAP_THRESHOLD, 0); 

在程序的開始將迫使的glibc的malloc的總是使用mmap(3)。如果我的假設是真的,那麼virt mem將會減少。我不建議使用它(對於小塊,它會導致大量內存開銷,並且總是用0來填充內存頁,從而導致CPU開銷),但是可以測試理論。

這只是與glibc。其他內存管理器(如tcmalloc)使用不同的策略。

我希望這有助於!

相關問題