Fragmentiert eigentlich der Speicher...



  • Optimizer schrieb:

    ... wenn man ausgiebig new und delete benutzt? Und was wird dann gemacht, wenn kein ausreichend großes, zusammenhängendes Stück mehr frei ist? Neuer Speicher angefordert?

    Mir ist grad langweilig. 🙄

    die begründungen für schlimme fragmenterung, die ich hin und wieder lese, sind alle fragwürdig.
    wie ist überhaupt dein new/delete implementiert? ein small objects allocator davor (slab-allocator)? der fragmentiert mal gar nicht wild. und dahinter ein buddy allocator? der eigentlich auch nicht. und drunter das bs, das mit magischen mitteln den physikalischen speicher seitenweise (4k oder 8k) nehmen kann und dir irgendwohin einblenden kann. also auch unzusammenhängenden speicher sammeln und dir zusammenhängend präsentieren.

    geh mal von keiner schlimmen fragmentierung aus. so 50% platzverschendung mögen sein, aber drüber hinaus sehe ich nichts.



  • Kann das BS Speicher defragmentieren, der gerade von meinem Programm benutzt wird? Das bezweifle ich irgendwie.
    Ich frag mich nur, was dann passiert. Angenommen, der Heap ist so fragmentiert, dass kein neues Objekt erstellt werden kann. Wird dann der Heap vergrößert? Und was passiert mit dem alten Müll? Theoretisch kann es ja passieren, dass ein Block Speicher nicht wieder an das BS zurückgegeben wird, nur weil da ein einziges langweiliges Objekt noch rumhockt, oder?



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Optimizer schrieb:

    Kann das BS Speicher defragmentieren, der gerade von meinem Programm benutzt wird? Das bezweifle ich irgendwie.
    Ich frag mich nur, was dann passiert. Angenommen, der Heap ist so fragmentiert, dass kein neues Objekt erstellt werden kann. Wird dann der Heap vergrößert? Und was passiert mit dem alten Müll? Theoretisch kann es ja passieren, dass ein Block Speicher nicht wieder an das BS zurückgegeben wird, nur weil da ein einziges langweiliges Objekt noch rumhockt, oder?

    du kannst deinen lokalen virtuellen adressraum fragmentieren.
    mal angenommen, du hast nur 2000k bytes frei. die 2000k seien zusammenhängend.
    a=new char[1000K];
    b=new char[1
    K];
    c=new char[999K];
    würde ja alles vollmachen.
    delete[] a;
    delete[] c;
    würde alles bis auf ein k wieder freimachen.
    aber danach klappt new char[1500
    k] nicht mehr, weil mittendrin ein k rumhängt.

    aber normalerweise haste 2G adressraum. wie will der voll werden? doch nur, indem man unsinnigerweise den ganzen video-film ins ram hauen will.

    haste grad mal kein physikalsches ram frei, dann macht das bs ein wenig frei, indem es anderen anwendungen was abnimmt (und in die auslagerungsdatei tut) und dir gibt. dazu muß es nur vorsorglich auch in der auslagerungsdatei platz für dein gerade gemachtes ram reservieren, den du mußt ja auch ausgelagert werden können. klappt das nicht, weil die auslagerungsdatei voll ist (unsinnigerweise nicht wachsen kann und auch 200M beschränkt ist), wirft new ne exception.

    aber nochmal zu dem bleistift oben:

    a=new char[1000K];
    b=new char[1
    K];
    c=new char[999*K];
    würde ja alles vollmachen.
    delete[] a;
    delete[] c;
    würde alles bis auf ein k wieder freimachen.
    und es wird sogar viel wieder ans BS zurückgegeben. das K bei b blockiert eine seite (der größe 4k). die anderen 499 seiten von a und c können fein dem bs zurückgegeben werden.

    aber das wird so nicht vorkommen, man ruft nicht für jeden furz das bs auf. wenn ich einfach nichts dem bs zurückgebe, sondern nur als freispeicher für weitere new-aufrufe von mir behalte, bin ich (msvc60) um faktor 70 schneller als das mitgelieferte new/delete. normaler wäre wohl, ein paar kilobytchen zu behalten, umd bei weiteren news echt schnell zu sein. 64k werden in ner normalen geschichte bestimmt in der auslagerungsdatei noch belegt sein, obwohl du im prog nur 1k nutzdaten halten tust.

    was nicht passiert, ist daß der physikalische speicher schlimm fragmentiert, nur weil man mal dieses, mal jenes programm startet, oder so. der physikalische ist eh ganz durcheinander und wird immer nur an die virtuellen adressen deines lokalen adressraumes gespiegelt.



  • Also entnehme ich deiner Erklärung, dass ein Programm, dass ordnungsgemäß ein paar Milliarden mal new und delete durcheinander aufruft, nicht immer mehr Speicher benötigt, vorausgesetzt, ich delete immer wieder alles. 👍



  • Optimizer schrieb:

    Also entnehme ich deiner Erklärung, dass ein Programm, dass ordnungsgemäß ein paar Milliarden mal new und delete durcheinander aufruft, nicht immer mehr Speicher benötigt, vorausgesetzt, ich delete immer wieder alles. 👍

    korrekt.

    nimm als maß den buddy allocator http://acm.uva.es/p/v8/827.html
    der frißt zwar von anfang an ein wenig mehr als nötig, aber man kriegt ihn nicht totfragmentiert und er bleibt auch in jeder lage lecker schnell.



  • Ein effizientes new und delete wird doch wohl hoffentlich standardmäßig implementiert sein??
    Ich schlag mich jetzt sicher nicht damit rum, eine eigene Speicherverwaltung zu coden. 🕶



  • Optimizer schrieb:

    Ein effizientes new und delete wird doch wohl hoffentlich standardmäßig implementiert sein??
    Ich schlag mich jetzt sicher nicht damit rum, eine eigene Speicherverwaltung zu coden. 🕶

    meine erste überraschung erlebte ich, als mein erster small object allocator keinen geschwindigkeitsgewinn brachte. offensichtlich hat der msvc60 sowas schon drin. und viel später hat es mich auch positiv überrascht, daß die verwaltungsinformationen nicht direkt bei den nutzdaten stehen. das ist natürlich klasse, wenn man eher selten new/delete macht und eher oft auf dem angelegten speicher arbeitet. zur not können die verwaltungsinfos minutenlang auf die platte ausgelagert werden, bis man sie für's delete wieder braucht. neulich las ich, daß der slab-allocator versucht, die daten in verschiedenen seiten ein wenig gegeneinander zu verschieben, damit unterschiedliche cache-lines benutzt werden. die small-object-allocators machen inzwischen kein locking mehr, sondern haben pro thread eine instanz.
    die ganzen tricks, die sich die leute da einfallen lassen, und die sich in jüngster zeit durchsetzen, kann man ja kaum alle verfolgen und nachimplementieren. und dann kommt der 64-bit-prozessor und man muß alle typen umbasteln. und weil mehr parallel läuft, sind ram-zugriffe noch katastrophaler als heute, wieder alle performance-einschätzungen überdenken und viel umbasteln. und überhaupt sind viele sachen anders spezifiziert, das alte
    if(p==0)
    {
    lock();
    if(p==0)
    p=init();
    unlock();
    }
    klappt nicht mehr. hab keine ahnung, wie die jungs das lösen werden. ich werde es nicht tun. also bleibt mir gar nichts anderes übrig, als normalerweise das standard-new/delete zu verwenden.

    für ein konkretes programm wird man immer ein new/delete bauen können, das ein wenig flotter als das standard-new/delete ist. zum beispiel nehme ich mal den trivialen fall, daß man am anfang des programms ganz viel new macht und am ende ganz viel delete. dann kann man auch drauf verzichten, delete überhaupt zu implemetieren und new greift sich einfach fortlaufend speicher.
    und offensichtlich ist es sauteuer, in jedem new/delete ein lock zu machen, nur weil ein anderer thread evtl auch am freispeicher spielen mag. falls man zufällig wüßte, daß nur ein thread objekte erzeugt und löscht, könnte die ganze thread-synchronisation im new/delete wegfallen.

    aber das bringt in normaloen anwendungen natürlich eh nix, weil die viel mehr zeit mit rechnungen und ausgaben verblasenrechnen als mit new/delete.

    und wer das globale new/delete reimplementiert, steckt eh seine nase in die vorhöllen des c++-schreckens.



  • Jojo, die Speicherverwaltung überlass ich besser jemand anderem, das ist nichts für mich. 🙄
    Am liebsten natürlich nem Garbage Collector. 😃 🤡



  • volkard
    *******

    hast du noch mehr brauchbare links zu dem thema? ich werd mir in C zwangsweise ein speichermangager basteln müssen, sonst seh ich bei den viellen mallocs und frees bald kein land mehr 😉
    was mich interessiert sind eher die algorithmen mit beschreibungen, vielleicht auch vereinzelte code fragmente

    bye

    tt



  • TheTester schrieb:

    volkard
    hast du noch mehr brauchbare links zu dem thema?

    eigentlich nicht. meine suchwörter waren vorwiegend "memory allocatr", "fast memory allocator", "buddy allocator", "slab allocator" und das hin und wieder bestückt mit "thread", "concurrency", "ia64" und so sachen. da kam aber überraschend wenig raus.
    was ich aber meine, herausgefunden zu haben, ist daß linux aktuell den einen namens "slab allocator" nimmt, und der echt fein ist und jeden modernen schnickschnack kann. und der ist ein buddy alloator (wie im link oben) mit nem small object allocator (wie in modern c++ design) dahinter. ich vertraue den nichtnutzigen linuxern in dieser hinsicht, daß die die zur zeit beste kombination sich rausgesucht haben. mach's also am besten ähnlich.

    ich werd mir in C zwangsweise ein speichermangager basteln müssen, sonst seh ich bei den viellen mallocs und frees bald kein land mehr 😉

    in C? ist doch unfug.

    afair waren ein paar free/mallocs für c als code beim djgpp (delorie.com) dabei.

    kann dir evtl auch helfen bei deinem. müßtest halt sagen, welche randbedingungen herrschen.



  • Modern C++ Design | ISBN: 0201704315

    behandelt einen ua. die Implementierung eines SmallObjectAllocators.


Anmelden zum Antworten