Hallo,
Dir geht es an sich ja nicht um virtuellen Adressraum
Doch genau darum geht es ja. Ich brauche eine freie virtuelle Adresse um physischen Speicher mappen zu können und wenn ich vorher nen kleinen Bereich genau dafür abzwacke und auch meine Datenstrukturen zur Verwaltung dieses Bereichs schon vorher allokiere dann habe ich das erreicht.
Achso. Ich würde das dann wahrscheinlich mit in die Verwaltung der virtuellen Adressen mit reinziehen, d.h. du nutzt den gleichen Code zum Verwalten deiner eigenen Strukturen wie auch zum Verwalten der fremden Strukturen. Wichtig ist halt, dass du nicht den gesamten VMM dafür nutzt, denn das geht nicht.
Das heißt, ich durchsuche den Baum insgesamt dreimal... einmal suche ich im Baum nach meinem Block. Beim zweiten Mal untersuche ich alle Blöcke, die kleiner sind als mein Block (und damit potentiell links angrenzen), beim dritten Mal untersuche ich alle Blöcke, die größer sind. Da lohnt es sich, jeden Block exakt einmal anzuschauen (Liste/Traversierung); im Durchschnitt untersuche ich ohnehin nur die Hälfte aller Blöcke.
Wieso so umständlich, dass machst du alles in einem Durchlauf! Du überprüfst jeden Knoten darauf, ob er eine der 3 Eigenschaften erfüllt und fertig.
Dann muss ich mir ohnehin jedes Element anschauen. Was sowieso eine Pflicht ist, wenn im Gesamtbereich Löcher existieren.
Stop, das darf er nicht.
Wenn er das bei dir nicht darf, ok, aber bei mir darf er das. Ist halt ne Design-Entscheidung.
Das heißt, ich darf mir ein Megabyte Speicher geben lassen und dann in einem Befehl die mittleren 333 KB freigeben? Seltsames Design.
Speicher ist heutzutage wirklich genug da
Sorry, aber mit dieser Einstellung kommst du bei mir nicht weiter, das ist wie CPU Leistung ist doch genug da, wozu nen komplizierten Baum nehmen, ne Liste ist viel einfacher!
Stop. Es geht um zwölf Megabyte im Worst Case bei einer vorhandenen Ressourcenmenge von drei Gigabytes. Das sind 0,39%. Im Worst Case.
Ein System mit 64 MB RAM wird in den seltensten Fällen etwas davon haben, wenn ein Prozess 3 GB RAM alloziiert. Mit RAM hinterlegen geht nur begrenzt (die arme Festplatte) und ohne RAM ist das eh fürn Popo.
Wenn man 1% der verfügbaren Ressourcen für die Verwaltung derselben gebraucht, dann ist das für mich ein sehr akzeptabler Kompromiss. Vergleiche mal die formatierte/unformatierte Größe deiner Diskette/Festplatte - nicht in Bezug auf Dateisysteme, sondern den realen Unterschied.
Wegen solcher Einstellungen werden die CPUs immer schneller, haben wir immer mehr RAM, aber die Programme werden immer langsamer!
Das ist eine Frage von Verhältnismäßigkeit.
Nein, du kannst keine Permissions prüfen.
Richtig, brauch ich nicht und will ich nicht. Wozu eigentlich?
Damit niemand (außer dem Kernel) ein Loch im Adressraum freigeben kann? Damit ein Userspace-Programm nicht durch wildgewordene Zeiger Speicher eines anderen Programms (oder des Kernels) freigeben kann? Von mir aus auch "basic sanity checks".
Dann kommt noch hinzu das es hier um allgemeinen Code geht, den man zur Verwaltung von all den Sachen nutzen kann, die sich halt auf Integer-Werte abbilden lassen.
Och, so wirklich auf Integerwerte beschränkt ist der Ansatz auch nicht... allerdings hat jede Ressource die Eigenschaft, (mindestens) einen Eigentümer zu besitzen, sofern sie benutzt ist, und keinen, wenn sie frei ist.
Ich kann mir keinen Anwendungsfall (mal abgesehen von richtig miesen memory leaks) vorstellen, bei dem du den Endspeicherverbrauch nicht mal näherungsweise abschätzen kannst und er trotzdem so groß werden kann.
Nen Server, ne DB usw.
Hä? Konkretisier mal.
Du weißt vorher nie mit wievielen Clients du es zu tun bekommst usw. und bei einer DB kannst du vorher auch nicht wissen wie groß die im Endeffekt wird.
Ich werde die Datenbank aber nicht in Bröckchen verarbeiten, d.h. der RAM-Maximalverbrauch ist in jedem Fall durch die Größe der DB beschränkt. Außerdem werden DBs grundsätzlich so optimiert, dass die mindestmögliche Menge an I/O stattfinden muss (Transaktionen), das heißt, die DB-Dateien werden in möglichst großen Blöcken von der Festplatte und damit in große Blöcke im RAM gelesen.
Bei reinen Datenservern wächst nur der Plattencache an, der ist aber für das System irrelevant und darf jederzeit wieder in Anspruch genommen werden - ist also auch kein Grund.
Ok, falsch ausgedrückt, ich meinte das ein Programm sagen, das es einen Bereich im virtuellen Speicher reservieren kann, der erst mit physischen Speicher hinterlegt wird, wenn das erste Mal darauf zugegriffen wird. Damit kannst du kein System lahmlegen.
Richtig, das meinte ich auch. Das würde ich wahrscheinlich mit einer automatischen Grenze lösen (die genannten 16 MB).
Wo siehst Du da einen Durchgriff? VMM und SlabAllocator sind auf einer Ebene und (leider) wechselseitig voneinander abhängig. Der SlabAllocator wird (neben dem VMM) von den verschiedenen Teilen im Kernel benutzt (er stellt ja den Kernel-Heap zur Verfügung) und der User-Space benötigt Segmente und holt sich diese vom VMM (natürlich über Kernel-Funktionen die zur Verwaltung der Segmente wieder den SlabAllocator benötigen). Ich sehe darin keine Probleme, wichtig ist nur das wenn SlabAllocator und VMM sich gegenseitig aufrufen der jeweils eigene Lock frei ist damit eben kein Dead-Lock entsteht.
Wenn man das so betrachtet, dann sind Slab-Allocator und VMM ein monolithischer Blob. Solange man dann nicht behauptet, dass es verschiedene Ebenen seien (wie ich es tue), dann ist das auch eine Lösung und das hatte das auch so gekennzeichnet.
Ich mag künstlich geschaffene Limits nicht. Da hätte ich ja gleich bei meinem alten Kernel-Design bleiben können
Da war alles künstlich begrenzt, Prozesse, Threads, Ports usw. Macht die Verwaltung natürlich wesentlich einfacher und schneller, aber inzwischen finde ich soll das System halt so genutzt werden was der Speicher hergibt ohne das ich es irgendwo künstlich begrenze.
Dynamische Verwaltung von Zeugs erfordert immer mehr Ressourcen als statische Verwaltung von Zeugs. Mal abgesehen davon haben Limits durchaus eine Berechtigung, sei es für Zugriffe (wieder die Permissions), sei es, um einen amok laufenden Prozess loszuwerden.
Wann tritt denn dein OOM-Killer in Kraft? Wenn der RAM [ohne Plattencache] voll ist, wenn ein Prozess mehr RAM möchte als physisch vorhanden oder wenn die Festplatte wegen Swap voll ist? Ist das System überhaupt noch benutzbar, wenn es swappt? (Mein Linux bricht komplett zusammen, wenn der RAM nahezu voll ist und der Auslagerungsmarathon losgeht. Je schneller der OOM-Killer dann zuschlägt, umso eher läuft das System überhaupt wieder.)
Alle normalen malloc-Implementierungen holen den virtuellen Speicher in größeren Blöcken herein und nicht jede Page einzeln. Wenn das OS in den virtuellen Speicher nicht sofort physische Pages mappt dann entsteht noch nicht mal eine Verschwendung des physischen Speichers.
Um mal wieder Haare zu spalten, wenn meine malloc-Implementation das nicht so macht ist deine Aussage schon automatisch falsch
Dann ist deine malloc()-Implementierung nicht 'normal'.
Ansonsten fordert malloc halt immer 16KB an, aber ich finde halt trotzdem das ein Programm die Möglichkeit haben sollte auch nur 4KB anzufordern und einen angeforderten Block muss es auch anders wieder freigeben dürfen.
Darum geht es nicht. Wenn 16 MB angefordert werden, dann wird dein VMM hoffentlich nicht anfangen, 4096 einzelne Pages zu verarbeiten, oder?
Ich meinte eigentlich das du nicht einfach nen Bereich im virtuellen Adressraum reservieren kannst und erst später (am besten Page-weise) mit physischen RAM hinterlegst.
Klar. Das ist recht teuer, wenn du sofort den RAM benötigst (durch die Masse an PageFaults) - dem kannst du vorbeugen, wenn du den RAM sofort bereitstellst. Letzteres ist aber RAM-Verschwendung, wenn die Anwendung den RAM eben nicht nutzt und nur vorbeugend reserviert.
Das ist natürlich ein nettes Feature, aber dabei muss man aufpassen das trotzdem nur Speicher herausgegeben wird der sich auch wirklich mit Pages hinterlegen lässt
Meinst du damit jetzt, das ich nicht 16MB an virtuellem Speicher rausgebe, obwohl ich nur noch 8MB an physischen RAM frei habe?
Dafür gibt es dann swapping. Wobei ich das für den Anfang nicht implementieren werde, da ich gar nicht wüsste wie.
Swapping ist so sehr langsam und für das System so sehr tot, wenn die Daten nicht im RAM liegen, dass du das nicht unbegrenzt erlauben darfst. Sonst legt ein malloc(2TB, MAP_NOW) für hinreichend große Festplatte dein System für mehrere Stunden vollständig lahm.
Eine sinnvolle Grenze (für kleine Systeme) liegt bei etwa 2*RAMSIZE für alle Prozesse und 0.75*RAMSIZE für einen einzelnen Prozess. Und ja, das ist ein künstliches Limit und kann für bestimmte Anwendungsfälle auch zur Laufzeit korrigierbar sein (vgl. Linux /sys/*).
Damit Du eben die Größe und auch andere Attribute der benutzten Blöcke kennst.
Zwei Sachen dazu, dass soll hier ein allgemeiner Ressourcen Allocator werden und wozu braucht man das?
Und? Was für Ressourcen hast du denn? Hier geht es konkret um virtuellen Adressraum, in meinem Geiste zusätzlich zur Verwaltung von z.B. I/O-Ports und IRQ-Leitungen, in deinem Geiste zusätzlich zur Verwaltung von IDs.
Für Adressraum/Ports/IRQs gibt es jeweils Eigentümer (oder freigegeben), außerdem ist das Ding in Bereiche sortiert, die Elemente werden selten einzeln alloziiert. Für IDs gibt es einen Eigentümer, nur in seltenen Fällen wird Blockweise gearbeitet (jedes Dateihandle eines Prozesses steht für sich allein, eine Page eines Prozesses eher nicht).
Ich bin bisher ganz gut damit ausgekommen, nur die freien Bereiche zu speichern und habe noch keinen Nachteil davon getragen (der etwas anderes rechtfertigen würde).
Dann werden wir dich wohl nicht davon überzeugen können. Eh ich jetzt wieder einen Streit lostrete, lasse ich es damit sein.
Zum Thema Speicherverschwendung. Nochmal zum worst-case, wenn man jetzt immer nur 4KB Blöcke allokiert und halt die vollen 3GB ausgenutzt hat, dann ist mein Baum leer und eurer mit 786432 Elementen voll. Finde ich ein wenig übertrieben
Korrekt. Mach das mal unter einem normalen Betriebssystem und schaue, wieviel RAM du rauskriegst, wenn du (a) immer 4k-Blöcke alloziierst und (b) alles an einem Stück haben möchtest. Beobachte bitte die Performance des Systems in beiden Fällen... mich würde interessieren, ob die bekannten Betriebssysteme mit so einer Workload klarkommen oder nicht.
Insbesondere rechne das mal auf 64bit hoch, da wird mein Baum seine größe behalten oder kleiner werden und eurer wird immer größer und das pro Prozess.
Da der Ansatz Blödsinn ist, ist die Schlussfolgerung ebenfalls Blödsinn.
Außerdem betrifft das, wenn man sinnvolle Limits einstellt (ja, das ist sinnvoll), nur Rechner, die auch genug RAM haben.
Andere Sache, die aber mehr Dateisysteme betrifft: Schiebe in einen Ordner mal 10k Dateien mit unterschiedlichen Größen (z.B. den WINXP-Installationsordner, für langsamere Systeme reicht auch der WIN31-Installationsordner). Gehe dann mit einem Dateimanager deiner Wahl dort rein. Merkt man die Wartezeit?
Du wirst mit jedem System eine gezielte Workload aufbauen können, die sämtliche Algorithmen in den worst case treibt. Die Frage ist, ob das System als Ganzes dann noch benutzbar und vor allem stabil bleibt (dann ist es auch DoS-sicher) oder ob dann Grenzfälle und race conditions auftreten, die dann Bugs triggern. Das ist für die Qualität eines OS mMn wichtiger... auch, wenn es hier nur um ein Hobby geht.
Gruß,
Svenska