Speicherverbrauch auslesen



  • Hallo !

    Ich suche verzweifelt nach eine Möglichkeit, wie man den Speicherverbrauch (RAM) auslesen kann, damit ich mein Programm darauf testen kann.
    Also im Grunde sowas wie WindowsTastManager->getMemoryUsage zu Beginn und dann wieder zu Ende, um den realen Verbrauch zu haben...

    Kennt jemand eine Möglichkeit?

    Vielen Dank!
    Jerome



  • ueberlade das globale new delete und delete[] und zaehl einfach mit, auf diese weise kannst du nicht nur start und endverbrauch ermitteln, sondern koenntest sogar durchgaengig bei jedem aufruf eine statistik loggen.



  • Hallo!

    Vielen Dank für Deine Antwort! Ich weiss zwar, was überladen ist, aber bin leider noch kein C++-Profi. Kannst Du mir vielleicht an einem kurzen Code-Beispiel sagen, wie ich dadurch den Speicherverbrauch auslesen könnte?

    Ich habe eine andere Möglichkeit gefunden, Infos zum Speicher zu bekommen:
    Es gibt die PrintMemoryInfo-Funktion von der Microsoft Platform SDK
    http://msdn2.microsoft.com/en-us/library/ms683219.aspx

    Leider klappt das Code-Beispiel auf meinem Rechner nicht, obwohl ich die psapi.h und die psapi.lib im projekt eingebunden hab (kommen trotzdem noch Linkerfehler...)

    #include <windows.h>
    #include <stdio.h>
    #include "psapi.h"
    
    void PrintMemoryInfo( DWORD processID )
    {
        HANDLE hProcess;
        PROCESS_MEMORY_COUNTERS pmc;
    
        // Print the process identifier.
    
        printf( "\nProcess ID: %u\n", processID );
    
        // Print information about the memory usage of the process.
    
        hProcess = OpenProcess(  PROCESS_QUERY_INFORMATION |
                                        PROCESS_VM_READ,
                                        FALSE, processID );
        if (NULL == hProcess)
            return;
    
        if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
        {
            printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
            printf( "\tPeakWorkingSetSize: 0x%08X\n",
                      pmc.PeakWorkingSetSize );
            printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
            printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n",
                      pmc.QuotaPeakPagedPoolUsage );
            printf( "\tQuotaPagedPoolUsage: 0x%08X\n",
                      pmc.QuotaPagedPoolUsage );
            printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n",
                      pmc.QuotaPeakNonPagedPoolUsage );
            printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n",
                      pmc.QuotaNonPagedPoolUsage );
            printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
            printf( "\tPeakPagefileUsage: 0x%08X\n",
                      pmc.PeakPagefileUsage );
        }
    
        CloseHandle( hProcess );
    }
    
    void main( )
    {
        // Get the list of process identifiers.
    
        DWORD aProcesses[1024], cbNeeded, cProcesses;
        unsigned int i;
    
        if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
            return;
    
        // Calculate how many process identifiers were returned.
    
        cProcesses = cbNeeded / sizeof(DWORD);
    
        // Print the memory usage for each process
    
        for ( i = 0; i < cProcesses; i++ )
            PrintMemoryInfo( aProcesses[i] );
    }
    

    Hat jemand vielleicht schonmal damit gearbeitet und könnte mir helfen?



  • wie kann man global den new /delete operator überladen...

    muss ja für alle Klassen gelten und funktionieren?



  • um für alle klassen den new und delete operator zu überladen würde ich mir eine eigene Basisklasse ableiten

    sowas wie

    AClass
    {
        virtual public AClass()
        {
            static int memusage += sizeof(AClass);
        }
    
        virtual public  ~AClass()
        {
            memusage -= sizeof(AClass);
        }
    }
    

    und jede klasse von dieser klasse ableiten und den basis constructor bzw destructor auf alle Fälle auch bei überladung aufrufen. die frage ist ob das mit sizeof klappt. Da müsste mal jemand einen tipp geben wie man bei abgeleiteten klassen die richtige größe bekommt.



  • mhh hab das auch mal getestet ...

    mit sizeof geht es ... aber es gibt nur ein Problem:

    pointer auf arrays sind immer 4bytes gross, obwohl das array 1000 bytes gross sein könnte, und in einer Klasse wird man spätestens durch zeichenketten auf arrays mit einfachen pointer stossen ...



  • Wie wärs stattdessen, wenn man für eine Basisklasse den op new überläd und dann immer von dieser ableitet:

    class Base
    {
        static std::size_t memCount_;
    public:
        static void* operator new(std::size_t size)
        {
            memCount_ += size;
            return ::operator new(size);
        }
    
        static void operator delete(void* p, std::size_t size)
        {
            memCount_ -= size;
            ::operator delete(p, size);
        }
        //analog für new[] und delete[]
    };
    

    Alexandrescu schreibt schon sinngemäß: "wenn die Compilerbauer so viel Aufwand betreiben, dem operator new die Größe bereitzustellen, waurm sollte das nicht nutzen?" 😉

    Edit: Op delete hinzugefügt.

    Edit2: Eventuell einen virtuellen Destruktor hinzufügen, falls man Polymorphismus betreiben will.



  • Ja, das wäre sicher eine Lösung, allerdings bekommt der "normale" op delete die Größenangabe nicht explizit mitgeteilt, sondern muß sie selber wissen (und um aus dem übergebenen Zeiger abzulesen, wie groß der Speicherblock dahinter ist, mußt du weit in die Tiefen der Heap-Verwaltung abtauchen).



  • Dann wundert es mich, dass Alexandrescus SmallObjectAllocator funktioniert :o

    Im Standard steht:

    A deallocation function can have more than one parameter. [...]
    If class T does not declare such an operator delete (mit einem Parameter) but does declare a member deallocation function named operator delete with exactly two parameters, the second of which has type std::size_t, then this funtion is a usual deallocation function.

    Nach dem ersten Absatz hätte ich gesagt, dass das zumindest in der Praxis portierbar ist. Nach dem zweiten Absatz, scheint mir das Standard zu sein.

    PS: Ich sollte mir mal eine Version vom Standard besorgen, die nicht kopiergeschützt ist.


Anmelden zum Antworten