2016-07-28 7 views
5

कुछ प्रोग्राम जो मैं वर्तमान में काम कर रहा हूं, मुझे लगता है कि इससे ज्यादा स्मृति मिलती है। तो मैं समझने की कोशिश कर रहा हूं कि glibc malloc trimming कैसे काम करता है।ग्लिबैक मॉलोक को ट्रिम करना

:

Arena 0: 
system bytes  = 112054272 
in use bytes  =  112 
Total (incl. mmap): 
system bytes  = 120057856 
in use bytes  = 8003696 
max mmap regions =   1 
max mmap bytes = 8003584 

हालांकि लगभग सभी स्मृति जारी किया गया था, इस परीक्षण कोड भी बहुत कुछ निवासी स्मृति में अपेक्षा से अधिक की खपत: (malloc_trim बुला बिना)

#include <malloc.h> 
#include <unistd.h> 

#define NUM_CHUNKS 1000000 
#define CHUNCK_SIZE 100 

int main() 
{ 
    // disable fast bins 
    mallopt(M_MXFAST, 0); 

    void** array = (void**)malloc(sizeof(void*) * NUM_CHUNKS); 

    // allocating memory 
    for(unsigned int i = 0; i < NUM_CHUNKS; i++) 
    { 
     array[i] = malloc(CHUNCK_SIZE); 
    } 

    // releasing memory ALMOST all memory 
    for(unsigned int i = 0; i < NUM_CHUNKS - 1 ; i++) 
    { 
     free(array[i]); 
    } 

    // when enabled memory consumption reduces 
    //int ret = malloc_trim(0); 
    //printf("ret=%d\n", ret); 

    malloc_stats(); 

    sleep(100000); 
} 

टेस्ट उत्पादन: मैं निम्नलिखित परीक्षण लिखा था

[[email protected]]# ps aux | grep test 
root  14662 1.8 0.4 129736 **118024** pts/10 S 20:19 0:00 ./test 

प्रक्रिया smaps:

0245e000-08f3b000 rw-p 00000000 00:00 0         [heap] 
Size:    109428 kB 
Rss:    109376 kB 
Pss:    109376 kB 
Shared_Clean:   0 kB 
Shared_Dirty:   0 kB 
Private_Clean:   0 kB 
Private_Dirty: 109376 kB 
Referenced:  109376 kB 
Anonymous:  109376 kB 
AnonHugePages:   0 kB 
Swap:     0 kB 
KernelPageSize:  4 kB 
MMUPageSize:   4 kB 
Locked:    0 kB 
VmFlags: rd wr mr mw me ac 
7f1c60720000-7f1c60ec2000 rw-p 00000000 00:00 0 
Size:    7816 kB 
Rss:    7816 kB 
Pss:    7816 kB 
Shared_Clean:   0 kB 
Shared_Dirty:   0 kB 
Private_Clean:   0 kB 
Private_Dirty:  7816 kB 
Referenced:   7816 kB 
Anonymous:   7816 kB 
AnonHugePages:   0 kB 
Swap:     0 kB 
KernelPageSize:  4 kB 
MMUPageSize:   4 kB 
Locked:    0 kB 

[[email protected]]# ps aux | grep test 
root  15733 0.6 0.0 129688 **8804** pts/10 S 20:20 0:00 ./test 

प्रक्रिया smaps (malloc_trim के बाद):

जब मैं कॉल परीक्षण के उत्पादन malloc_trim को रहता सक्षम लगभग एक ही:

ret=1 
Arena 0: 
system bytes  = 112001024 
in use bytes  =  112 
Total (incl. mmap): 
system bytes  = 120004608 
in use bytes  = 8003696 
max mmap regions =   1 
max mmap bytes = 8003584 

हालांकि, आरएसएस काफी कम हो जाती है

01698000-08168000 rw-p 00000000 00:00 0         [heap] 
Size:    109376 kB 
Rss:     8 kB 
Pss:     8 kB 
Shared_Clean:   0 kB 
Shared_Dirty:   0 kB 
Private_Clean:   0 kB 
Private_Dirty:   8 kB 
Referenced:   8 kB 
Anonymous:    8 kB 
AnonHugePages:   0 kB 
Swap:     0 kB 
KernelPageSize:  4 kB 
MMUPageSize:   4 kB 
Locked:    0 kB 
VmFlags: rd wr mr mw me ac 
7f508122a000-7f50819cc000 rw-p 00000000 00:00 0 
Size:    7816 kB 
Rss:    7816 kB 
Pss:    7816 kB 
Shared_Clean:   0 kB 
Shared_Dirty:   0 kB 
Private_Clean:   0 kB 
Private_Dirty:  7816 kB 
Referenced:   7816 kB 
Anonymous:   7816 kB 
AnonHugePages:   0 kB 
Swap:     0 kB 
KernelPageSize:  4 kB 
MMUPageSize:   4 kB 
Locked:    0 kB 

malloc_trim को कॉल करने के बाद, ढेर शंकु हो गया। मुझे लगता है कि 8 एमबी एमएमएपी सेगमेंट अभी भी उपलब्ध स्मृति के आखिरी टुकड़े के कारण उपलब्ध है।

क्यों ढेर trimming स्वचालित रूप से malloc द्वारा नहीं किया जाता है? क्या मॉलोक को कॉन्फ़िगर करने का कोई तरीका है कि ट्रिमिंग स्वचालित रूप से की जाएगी (जब यह उस स्मृति को अधिक से बचा सकता है)?

मैं glibc संस्करण 2.17 का उपयोग कर रहा हूं।

+0

यदि आप बहुत सारी मेमोरी का उपयोग कर रहे हैं और इसे विशेष तरीकों से संभालने की ज़रूरत है, तो मैं विंडोज़ पर 'एमएसएपी' और 'वर्चुअलअलोक' का उपयोग करके इसे स्वयं करने की सलाह देता हूं। –

उत्तर

4

ऐतिहासिक कारणों से बड़े पैमाने पर, छोटे आवंटन के लिए स्मृति brk सिस्टम कॉल के साथ प्रबंधित पूल से आता है। यह एक बहुत पुराना सिस्टम कॉल है - कम से कम Version 6 Unix जितना पुराना - और केवल एक चीज यह कर सकती है "एरिना" के आकार को बदलें, जिसकी स्मृति में स्थिति तय की गई है। इसका मतलब क्या है, brk पूल अभी भी आवंटित एक ब्लॉक से कम नहीं हो सकता है।

आपका प्रोग्राम स्मृति के एन ब्लॉक आवंटित करता है और फिर उनमें से एन -1 को हटा देता है। एक ब्लॉक जो इसे हटा नहीं देता है वह उच्चतम पता पर स्थित है। यह brk के लिए सबसे खराब स्थिति परिदृश्य है: आकार को कम नहीं किया जा सकता है, भले ही 99.99% पूल का उपयोग न किया जाए! यदि आप अपना प्रोग्राम बदलते हैं, तो यह ब्लॉक array[0]array[NUM_CHUNKS-1] के बजाय मुक्त नहीं है, तो आपको अंतिम कॉल पर free पर आरएसएस और पता स्थान दोनों को कम करना चाहिए।

जब आप स्पष्ट रूप से malloc_trim पर कॉल करते हैं, तो यह लिनक्स एक्सटेंशन, madvise(MADV_DONTNEED) का उपयोग करके इस सीमा के आसपास काम करने का प्रयास करता है, जो भौतिक RAM जारी करता है, लेकिन पता स्थान नहीं (जैसा कि आपने देखा है)। मुझे नहीं पता कि यह केवल एक स्पष्ट कॉल पर malloc_trim पर क्यों होता है।

संयोग से, 8 एमबी एमएमएपी सेगमेंट array के प्रारंभिक आवंटन के लिए है।

+0

आपके उत्तर के लिए धन्यवाद! मैंने देखा कि 'सरणी' वास्तव में 8 एमबी सेगमेंट पर रहता है, और मैंने यह भी देखा कि 'सरणी [एन -1] 'हीप सेगमेंट के ** एंड ** पर रहता है। यदि यह इसके अंत में है, तो अब मैं समझ नहीं पा रहा हूं कि इसे कैसे छंटनी की जा सकती है (जब 'malloc_trim' को कॉल करते हैं)। – michael

+0

पढ़ें मैंने फिर से 'madvise' के बारे में क्या कहा ... – zwol

+0

मैं समझता हूं, धन्यवाद। क्या आरएसएस मेमोरी की मात्रा को कम करने के लिए मेरे पास कोई रास्ता है? हर समय और फिर 'malloc_trim' को कॉल करने के अलावा? – michael

संबंधित मुद्दे