>>156347>War zu faul in den Quelltext zu schauen, meine mich aber erinnern zu können, dass Meister Zuse sicher keine "handelsübliche" Datenbank benutzt.
Ja, die ist handgefrickelt. Im Grunde genommen ist das einfach nur ein Speicherabbild mit einem zusätzlichen Journal, um Atomizität zu gewährleisten, falls mal während eines Updates der Strom ausfällt oder so.
Warum handgefrickelt? Dazu kleine Geschichtsstunde: Diätkanal entstand in den ganz früher Anfangsphasen von Kohlkanal, als jener noch vichan einsetzte, bei Cockbox gehostet war, und mit erheblichen Performanzproblemen zu kämpfen hatte. Es wurde damals über einen Umstieg auf Lynxchan nachgedacht, der ja später dann auch erfolgte, aber Zuse war und ist kein Freund von diesem Node+MongoDB-Geraffel (der Kot war zuminest damals auch absolut scheußlich) und es zirkulierte bereits das Mem, man könnte da doch was mit dietlibc, tinyldap und libowfat...
Irgendwann hat Zuse das dann aus einer Laune heraus einfach mal eben schnell an einem Wochenende gemacht (so ungefähr), eigentlich als Witz. Der Anspruch von Diätkanal war eigentlich, so eine Art Anti-Lynxchan sein. Unter anderem deswegen gibt es hier ja auch kein JS, weder server- noch clientseitig. Eigentlich wollte Zuse damals auch stilecht tinyldap als Datenbank nehmen, aber dazu kam es nicht aus folgenden Gründen:
- Zuse kapiert diesen LDAP-Scheiß nicht. Sich in LDAP einzuarbeiten hätte länger gedauert, als das ganze Brett zu programmieren, und hätte keinen Spaß gemacht.
- tinyldap untersützte damals keine Löschvorgänge, war für ein Bilderbrett also absolut ungeeignet.
- Es wurde nach anderen Alternativen gesucht: sqlite war immer noch zu bloatig, hätte den Fußabdruck um Größenordnungen erhöht. (sqlite umfasst alleine ungefähr 250k Zeilen, Diätkanal damals 9k). Und da das Brett natürlich dietlibc verwenden sollte, hätte sqlite natürlich aus der Quelle kompiliert werden müssen. Aber das hätte die Wahrscheinlichkeit, dass irgendwer diese Weichware tatsächlich ausprobiert, extrem verringert, weil niemand mal eben 250k Zeilen auditiert um zu prüfen, dass da nichts böses drin versteckt ist. Zuse wollte ursprünglich eigentlich nur die Weichware zeigen, das zugehörige Brett war gar nicht geplant und sollte eigentlich nur als Demo dienen, weil Zuse dachte, dass sich ohne Lebend-Demo das eh keiner anschaut.
- BerkeleyDB wurde auch noch evaluiert, und Zuse hat sich ein paar Ideen dort abgeschaut, aber es schien einfacher, es einfach selbst zu implementieren.
- Zuse wollte das schon immer mal machen.
- Bei herkömmlichen Datenbanken hat man immer extrem viel Klebe-Kot zwischen der Datenbank und den klientseitigen Strukturen (Stichwort ORM, Active Record, etc.). Diätkanal sollte aber minimalistisch sein (was unter anderem eine möglichest geringe Zeilenanzahl bedeutet) und da schien es am einfachsten, einfach direkt die Strukturen aus dem Arbeitsspeicher wiederzuverwenden und auf die Platte zu schreiben.
Vorteile dieses Ansatzes:
- Es kommt tatsächlich mit relativ wenig Kot aus und funktioniert seit Jahren ziemlich zuverlässig. Ist auch tatsächlich schnell und hat wenig Overhead (kein zusätzlicher Datenbankprozess nötig, kein Parsen von SQL, keine Kommunikation über Sockets).
Nachteile:
- Man kann nicht mal eben das Schema ändern, weil es Binärdaten in einem festen Format sind.
- Datenbank hat aufgrund des sehr einfachen Speicherallokators die Tendenz mit der Zeit zu fragmentieren, auch wenn das in der Praxis kein wirkliches Problem darstellt, weil die Datenbank auch dann immer noch recht klein ist. (Falls man die Datenbank doch mal defragmentieren möchte, kann man aber auch einfach nach JSON exportieren und anschließend wieder importieren, s.u.)
- Die in den Speicher gemappten Seiten sind prinzipbedingt Copy-On-Write. Das heißt, die Anzahl der residenten Seiten steigt mit der Laufzeit des Diätkanal-Prozesses stetig an. Könnte man lösen, indem man in regelmäßigen Abständen die Datenbank neu reinmappt, wurde aber nie implementiert, weil der Speicherbedarf ohnehin so gering ist, dass es sich nicht lohnt.
- Es gibt bisher nur die Möglichkeit, eine begonnene Transaktion zu committen, Rollback wurde nie implementiert, auch wenn es prinzipiell kein großes Kunststück sein sollte. Es besteht einfach nur kein Bedarf aktuell.
- Man muss beim Programmieren etwas aufpassen, dass man bei Schreibzugriffen auch tatsächlich den geänderten Speicher invalidiert, damit der Inhalt ins Journal und schließlich in die Datenbank geschrieben wird. Ansonsten wäre der halt nach dem nächsten Neustart weg und man hätte eine zerfickte DB. Das ist aber nur an ein paar wenigen Stellen relevant, in 99% der Fälle regeln die Macros das automatisch. Aber ein C-Programm ohne Risiko wäre eben kein richtiges C-Programm.
- Wie gesagt, Schema-Änderungen nicht einfach möglich, aber es war in den 7 Jahren Betriebszeit natürlich trotzdem mal hier und da nötig, ein neues Feld hinzuzufügen oder ähnliches. Deshalb wurde eine JSON-Import- und -Export-Möglichkeit hinzugefügt. Der Import und Export ist rasant schnell (dauert etwa 0ms), wurde aber von Hand nachträglich drangefrickelt und dadurch gibt es eine redundante Parallelstruktur. Man muss bei Änderungen an den Datenstrukturen also immer daran denken, auch den JSON-Import und -Export-Kot anzupassen. Vor einiger Zeit wurden in den meisten structs aber auch ein paar ungenutzte, reservierte Felder hinzugefügt, sodass das seltener notwendig sein sollte.
- Zuse hatte immer mal überlegt, ob man diese Parallelstrukturen zwischen Datenbank und JSON mit cleveren Macros eliminieren könnte, die Lösungen waren am Ende aber immer irgendwie länger als der bestehende Kot, hatten ein paar Nachteile, und waren für Uninitiierte schwerer zu verstehen. Dietchan hat aber auch den Anspruch, leicht verständlichen Kot zu haben und von Dritten anpassbar zu sein (auch hier wieder Antithese zu Lynxchan, das Erweiterbarkeit/Anpassbarkeit über 9000 Steckeins löst).
- Weil die Datenbank im Wesentlichen einfach nur ein Memory-Dump ist, ist sie Endian-abhängig. Man kann also nicht einfach die DB von einem Little-Endian- auf ein Big-Endian-System umziehen (oder umgekehrt), ohne vorher nach JSON zu exportieren und hinterher wieder zu importieren. In der Praxis nicht wirklich ein Problem, weil sowieso jeder vernünftige Mensch Little-Endian einsetzt, weil Big-Endian kernbehindert ist. Wer Big-Endian einsetzt, ist vogelfrei.
- Die DB-Implementierung benutzt an ein paar Stellen Bitfields, was eigentlich keine gute Idee ist, weil deren Speicherlayout implementierungsabhängig ist. In der Praxis noch nie ein Problem gewesen, sollte man aber vielleicht mal ändern. Zuse war aber bisher zu faul.
Alles in allem funktioniert es aber immer noch sehr gut. Aktuell residenter Speicher von dietchan: 10.7m. Und das umfasst alles.jpg, nicht nur die DB (auch wenn der Großteil davon die DB sein dürfe). Mach das mal mit MySQL, Postgres, MongoDB o.ä. Siehe auch
>>1. Da hat sich eigentlich nicht viel geändert seitdem. Bei den vichan-Bankmarken dort hat Zuse damals sogar vergessen, die MySQL-Datenbank miteinzuberechnen. (Und die extrem geringe Latenz kam auch nur daher, dass dort nur Lesezugriffe getestet wurden und vichan statische Seiten generiert, d.h. ist eigentlich nur die Performanz von nginx bzw. sendfile(), während bei Diätkanal alles dynamisch generiert wird. Also nicht mal ein fairer Vergleich. Die schlechte Performanz beim Kohlkanal kam damals auch durch die vielen Schreibzugriffe und dass dadurch für jeden neuen Pfosten zig HTML-Seiten neu generiert weren mussten).
>>156339>Hier im Diätkanal sind die Pfostennummern aber brettunabhängig,
Ja, das hat sich auch eher zufällig so ergeben. D hatte Zuse damals schlicht nicht dran gedacht, dass die bei klassischen Brettern ja pro-Brett sind. Allerdings hat letzteres wohl auch bloß historische Gründe: Die allerersten Brettweichwaren waren irgendwelche Perl-Skripte, bei denen man tatsächlich für jedes Unterbrett einen Ordner angelegt hat und das Skript in jeden Ordner einzeln reinkopiert hat. Eigentlich macht eine globale ID mehr Sinn, hat auch den Vorteil, dass man einen Faden leicht in ein anderes Brett verschieben kann, ohne irgendwas am Pfostentext anpassen zu müssen.
>entweder müsste Zuse dann eine Funktion einfügen, die jedes Mal prüft, ob die Pfostennummer schon existiert, oder gleich von uint32 auf uint64 wechseln, was ja sowieso viel hardwarenäher wäre.
Wie
>>156335 bereits schrieb nicht notwendig, da alle IDs von Anfang an bereits uint64 sind. Bis das überläuft, existiert unsere Zivilisation schon lange nicht mehr.