2010-12-15 16 views
6

अगले नमूना आवेदनमुफ्त मेमोरी के बाद मेरे प्रोग्राम का मेमोरी उपयोग सामान्य पर क्यों नहीं आता है?

program TestMemory; 


{$APPTYPE CONSOLE} 

uses 
    PsAPI, 
    Windows, 
    SysUtils; 

function GetUsedMemoryFastMem: cardinal; 
var 
    st: TMemoryManagerState; 
    sb: TSmallBlockTypeState; 
begin 
    GetMemoryManagerState(st); 
    result := st.TotalAllocatedMediumBlockSize + st.TotalAllocatedLargeBlockSize; 
    for sb in st.SmallBlockTypeStates do 
    begin 
     result := result + sb.UseableBlockSize * sb.AllocatedBlockCount; 
    end; 
end; 

function GetUsedMemoryWindows: longint; 
var 
    ProcessMemoryCounters: TProcessMemoryCounters; 
begin 
    Result:=0; 
    ProcessMemoryCounters.cb := SizeOf(TProcessMemoryCounters); 
    if GetProcessMemoryInfo(GetCurrentProcess(), @ProcessMemoryCounters, ProcessMemoryCounters.cb) then 
    Result:= ProcessMemoryCounters.WorkingSetSize 
    else 
    RaiseLastOSError; 
end; 

procedure Test; 
const 
    Size = 1024*1024; 
var 
    P : Pointer; 
begin 
    GetMem(P,Size); 

     Writeln('Inside'); 
     Writeln('FastMem '+FormatFloat('#,', GetUsedMemoryFastMem)); 
     Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows)); 
     Writeln(''); 

    FreeMem(P); 
end; 

begin 
     Writeln('Before'); 
     Writeln('FastMem '+FormatFloat('#,', GetUsedMemoryFastMem)); 
     Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows)); 
     Writeln(''); 

     Test; 

     Writeln('After'); 
     Writeln('FastMem '+FormatFloat('#,', GetUsedMemoryFastMem)); 
     Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows)); 
     Writeln(''); 
     Readln; 
end. 

एप्लिकेशन द्वारा लौटाए गए परिणामों पर विचार

Before 
FastMem 1.844 
Windows 3.633.152 

Inside 
FastMem 1.050.612 
Windows 3.637.248 

After 
FastMem 2.036 
Windows 3.633.152 

मैं जानता हूँ कि क्यों स्मृति के उपयोग के परिणाम Before और After में अलग हैं चाहते हैं:

+0

@ ओप्टिमल सिनिक - क्या यह वास्तव में चालाक है? ऐसा लगता है कि मेरा आवेदन 160 एमबी नहीं लौटाता है। 1 जीबी या रैम (या कम) वाले कंप्यूटर पर यह रैम का अपशिष्ट नहीं है? विवरण: http://stackoverflow.com/questions/4463979/my-program-never-releases-the-memory-back- क्यों – Ampere

उत्तर

11

कोई मेमोरी मैनेजर (फास्टएमएम समेत) कुछ ओवरहेड में पड़ता है, अन्यथा डेल्फी विंडोज मेमोरी प्रबंधन का उपयोग कर सकता था।

  • संरचनाओं कि FastMM स्मृति के उपयोग का ट्रैक रखने के उपयोग करता है, स्मृति के
  • टुकड़े कि FastMM अभी तक विंडोज स्मृति प्रबंधन में वापस नहीं आते समान स्मृति अनुकूलन करने के लिए:

    अंतर आप देखेंगे भूमि के ऊपर है भविष्य में आवंटन

+0

क्या आप टिप्पणी कर सकते हैं, कृपया, "अंदरूनी - विंडोज" मान – Branko

+0

@ ब्रैंको कृपया अपनी टिप्पणी समझाएं, क्योंकि मुझे समझ में नहीं आता कि आप मुझसे क्या उम्मीद करते हैं। –

+0

@ जेरोइन वाइर्टप्लाइमर शायद (बस अनुमान लगा रहे हैं) वह ओपी के टेस्टमेमरी एप्लिकेशन की वापसी के बारे में बात कर रहा है। 'अंदर ... विंडोज 3.637.248' – EMBarbosa

2

चूंकि मेमोरी मैनेजर प्रदर्शन को तेज करने के लिए पृष्ठभूमि में चालाक चीजें कर रहा है।

+0

उदाहरण के लिए क्या? अगर प्रक्रिया मेमोरी से बड़ी मात्रा में डेटा जारी करती है, तो संदर्भ या जो कुछ भी रखने का कोई कारण नहीं है, तो मैं कहूंगा कि आदर्श रूप से स्मृति आकार पहले निष्पादन के समान होना चाहिए। –

+1

आदर्श रूप से निर्भर करता है कि आप आकार से अधिक गति पसंद करते हैं। –

+0

और चालाक संदर्भ पर भी निर्भर करता है। एक बेहद चालाक मेमोरी मैनेजर दोनों बड़े, जटिल बहुप्रचारित अनुप्रयोग के पदचिह्न को गति और कम कर सकता है - "आवंटित, फिर तुरंत हटा दें" मामले में स्मृति बर्बाद करने की कीमत पर। मुझे डेल्फी के मेमोरी मैनेजर के बारे में पता नहीं है कि यह वास्तव में क्या कर रहा है, लेकिन मुझे पता है कि आप किसी भी उचित आकार के आवेदन के लिए प्रश्न में उदाहरण से बाहर नहीं निकल सकते हैं। –

0

यह getmem/malloc/free कैसे काम करता है?

ढेर संभाजक - malloc द्वारा प्रयोग किया जाता के रूप में ...

1) आंतरिक स्मृति के बड़े हिस्से (आमतौर पर 1Megabyte अप करने के लिए 64K) और फिर आप 100byte और 200byte वस्तुओं देने के लिए और अप करने के लिए उप-विभाजित किया हिस्सा आवंटित कार्यक्रम में तार। जब आप मुफ्त मेमोरी करते हैं तो वह जगह होती है जहां वह आंतरिक बफर या खंड में आवंटित किया गया था, फिर उसे मुफ्त में चिह्नित किया जाता है। कुछ भी वास्तव में नहीं होता है!

2) तो आप स्मृति के बड़े हिस्से की सूची के रूप में HEAP के बारे में सोच सकते हैं, और आपके प्रोग्राम में सभी ऑब्जेक्ट्स उन हिस्सों के केवल छोटे हिस्से हैं।

3) स्मृति के बड़े आंतरिक भाग केवल तभी मुक्त होते हैं जब उनके अंदर की सभी वस्तुओं को मुक्त कर दिया जाता है, इसलिए सामान्य मामला यह है कि जब आप कुछ वस्तु मुक्त करते हैं तो वास्तव में कुछ बिट्स उपलब्ध होने के अलावा चिह्नित नहीं होते हैं।

यह ढेर प्रणाली का एक काफी बेवकूफ वर्णन है, लेकिन अधिकांश ढेर एक ही तरीके से काम करते हैं, लेकिन उससे कहीं अधिक अनुकूलन करते हैं। लेकिन आपका सवाल यह है कि स्मृति क्यों नहीं जाती है और जवाब इसलिए है क्योंकि वास्तव में कुछ भी मुक्त नहीं होता है। स्मृति के आंतरिक पृष्ठों "नया" या "malloc" आदि के बगल में कॉल के लिए रखा जाता है ...

चित्र आईटी

अंदर ढेर 100Kb

में से एक विशाल ब्लॉक
You call "malloc(1000)" or "getmem(1000)" to get a 1K block of memory. 

तब सभी है ऐसा होता है कि स्मृति के 1 के ब्लॉक को उस ब्लॉक में उपलब्ध 99K मेमोरी छोड़कर स्मृति के 100kb ब्लॉक से लिया जाता है। यदि आप मॉलोक या गेटम कॉलिंग करते रहते हैं तो यह तब तक बड़े ब्लॉक को विभाजित रखेगा जब तक कि इसे किसी अन्य बड़े ब्लॉक की आवश्यकता न हो।

मॉलोक या गेटम के लिए कॉल के साथ आवंटित स्मृति का प्रत्येक छोटा ब्लॉक वास्तव में 16 या 24 अतिरिक्त बाइट्स (आवंटन के आधार पर) अतिरिक्त मेमोरी प्राप्त करता है। यह स्मृति बिट्स है कि आवंटक यह जानने के लिए उपयोग करता है कि आवंटित किया गया है और जहां इसे आवंटित किया गया है।

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