Hallo,
Zumal du äußerst selten einen solchen Algorithmus brauchen solltest, insbesondere nicht für interne OS-Strukturen. Da hast du normalerweise nur selten mehr als 10k Elemente.
Wer redet hier von internen OS-Strukturen, es ging im den UserSpace und das der Stack eventuell zu klein ist um z.B. ein QuickSort auf einer größeren Datenmenge durchzuführen.
Richtig, ich hab das versehentlich auf eine universelle Sortierroutine verallgemeinert. Trotzdem glaube ich, dass du bei Anwendungen, die eventuell in so ein Limit laufen könnte, dies vorher weißt und den Stack im Voraus hinreichend groß machen kannst. Möglicherweise kann das sogar die Anwendung selbst tun.
Wenn du mir, nur weil ich es gerne in erster Instanz einfach, simpel und dumm baue, unterstellst, ich solle das Programmieren sein lassen, dann solltest du im Gegenzug mal deine Konzepte überdenken... denn dann ist irgendetwas grob falsch.
Sorry, aber du hast ja selbst gesagt, dass du es mit Threading nicht so hast, weil dir das zu kompliziert ist und du zeigst in deinen Antworten oft das du lieber alte Wege gehst als neue auszuprobieren.
Ich sehe halt wenig Notwendigkeit, gute, bekannte Konzepte wegzuwerfen. Wenn etwas allerdings nicht optimal funktioniert, dann suche ich auch nach neuen Konzepten. Das mag sich mit deinem Wesen beißen, aber bisher bin ich damit gut gefahren. Never touch a running system, solange es die Aufgabe vollständig erfüllt.
Ich sage nicht das du dumm bist, aber was Software betrifft die irgendwo produktiv im Einsatz ist sollte die nicht so programmiert sein, das sie "alt" ist.
Erklär das mal deiner normalen Qualitätssicherung. Und ich habe auch wenig Interesse, dass in einem Flugzeug der Autopilot neue Wege "ausprobiert". Das ist eine Frage der Stabilität. Apache geht z.B. immernoch auf 1994 zurück, wenn sich die Codebasis zwischendurch auch mehrfach verändert hat, aber nach außen ist es dasselbe.
Denn das ist wieder genau das was ich schonmal gesagt habe, wir haben immer schnellere CPUs, immer mehr CPUs in einem System, immer mehr RAM, aber die Programme werden immer langsamer!
Das liegt definitiv nicht an den ausgetretenen Konzepten, von SMP mal abgesehen. Du kannst mit simplem C und einem hinreichend antiken Vorgehen mit hinreichend antiken Werkzeugen auf moderner Hardware einen hochgradig performanten Webserver bauen. Solange der Ruf aber eben nicht nach Effizienz, sondern nach Features geht, wirst du Bloat produzieren. Das sind Dinge wie KDE, Gnome oder auch Firefox - Features ohne Ende auf Kosten der Performance.
Und solange man Features vor Optimierung stellt, wächst Software auch immer schneller als die dazugehörige Hardware. Heutige PC-Spiele sind so gebaut, dass sie mit Maximaleinstellungen auf Rechnern laufen, die erst in 1-2 Jahren existieren werden! Das ist dann auch eine Wirtschaftsfrage. "Was lange hält, bringt kein Geld." Effiziente Bürosoftware (Office 2000) reicht für 90% aller Anwendungsfälle hin, würde aber keinen neuen Rechner erforderlich machen. Das ist Absicht!
Solange es immer kleine, schnelle Alternativen gibt, habe ich damit auch kein Problem.
Die zyklische Abhängigkeit kommt, wenn du malloc in der libc implementierst, im Kernel aber gerne ein malloc/kmalloc benutzen möchtest. Da du das nicht tust, sondern deinen Slab-Allocator benutzt, ist das für dich nicht relevant.
Ich habe das mit der zyklischen Abhängigkeit immernoch nicht verstanden. Denn darunter verstehe ich das die untereinander abhängig sind, aber das sehe ich halt nicht bzw. nicht das Problem.
Der Kernel kann keine im Userspace implementierten Funktionen nutzen. Implementierst du malloc im Userspace (libc), kann der Kernel das nicht nutzen. Tut er es doch, hast du zyklische Abhängigkeiten.
Ja ich nutze nur meinen SlabAllocator, aber was außer des Algos für die Verwaltung des Speichers unterscheidet den denn von einem normalen malloc()?
Eben genau der. Es ist ein anderer.
Variablen, die du nur in einer Funktion benutzt, kannst du auf den Stack legen. Rufst du eine Funktion auf, wird der Rücksprungpointer dahinter gelegt, ist also egal (die Zeiger bleiben gültig), bei einem Rücksprung würdest du an die falsche Adresse (nämlich den Inhalt der Variablen) springen. Um das zu vermeiden, nutzt man Magic Cookies, die Variablen von Rücksprungadressen trennen und ein Stack-Unwinding, was vom Compiler erledigt wird.
Was du beschreibst braucht also Support vom Compiler und ist ohne diesen nicht möglich. Was passiert wenn ein solches Programm eine Library benutzt die sowas nicht unterstützt?
Dann findet es nicht statt. Entweder, der Compiler macht ein Stack-Unwinding (sollte er eigentlich sowieso) oder er tut es nicht. Danach richtet sich, ob dein malloc() bestimmte Dinge auf dem Stack alloziieren kann oder eben nicht.
Also Stack-Unwinding halte ich schonmal für Performance schädlich und den VMM brauchst du trotzdem, denn wer soll denn den Stack verwalten (Multi-Threading)?
Stack-Unwinding ist eigentlich nur, dass du den Stack-Pointer nicht verschiebst, ohne die Daten vorher wieder vom Stack runterzunehmen. Das heißt, dass du zusätzliche (OS-)Daten, die malloc() da hingelegt hat, auf dem Stack haben darfst und diese auch nutzen kannst - und du vor einem Rücksprung aus einer Funktion brav alle Daten wieder abräumen musst.
Willst Du den Stack als Heap benutzen? Das geht IMHO definitiv in die Hose, da helfen auch keine "Magic Cookies".
Bringt aber Performance, wenn du Variablen nur innerhalb einer Funktion und darunterliegenden Funktionen benutzt und der Stack ausreichend groß ist. Grund ist vor allem Cache-Lokalität und, dass du keinen Syscall für Speicher brauchst, dieser Speicher nicht extra vom System verwaltet werden muss (die Verwaltung dessen findet im Userspace statt, der Stack als Ganzes gehört ohnehin zum Thread).
Und wenn ich im Kernel keine "full-featured-malloc-Umgebung" will/brauche? Gerade bei einem Micro-Kernel besteht danach absolut kein Bedarf. Ich will auch mit einem speziell für meinen Kernel optimierten SlabAllocator auskommen und sonst nichts, ich hab ja auch eine gute "full-featured-malloc-Umgebung" für den User-Space.
Dann fällt natürlich alles, was ich gesagt habe, weg - wenn du etwas nicht brauchst/willst, musst du es nicht implementieren.
Eine Heap-Implementierung lässt sich doch nur in so fern optimieren, dass das alloc() und free() schnellst möglich und mit möglichst wenig Speicherverbauch/Verschnitt passiert.
Das hängt vom Anwendungsfall ab. Eine Rekursion, die in jedem Rekursionsschritt eine Integer-Hilfsvariable benutzt, optimiert sich anders als ein Videoschnittprogramm, welches für jedes Bild mit 9 MB (1920x1200x4) arbeitet und hunderte Bilder gleichzeitig im Speicher hält. Zumal "schnell" und "wenig Verschnitt" sich gegenseitig ausschließen, du also einen Kompromiss finden musst und genau der beste Kompromiss wieder vom Anwendungsfall abhängt. (Du siehst das anders.)
Gruß,
Svenska