5 Punkte von GN⁺ 2023-07-04 | 1 Kommentare | Auf WhatsApp teilen
  • Die Online-Ausgabe von Data-Oriented Design ist frei verfügbar, damit Leserinnen und Leser die Kerninhalte kostenlos ansehen können, um datenorientiertes Design zu lernen
  • Einige nicht zentrale Kapitel des gesamten Buchs fehlen, aber der Inhalt ist auf die für das Lernen nötigen wesentlichen Inhalte fokussiert
  • Da das Dokument automatisch von LaTeX nach HTML konvertiert wurde, können Formatierungsfehler, beschädigte Bilder und fehlerhafte Quellcode-Listings enthalten sein
  • Bei beschädigten Quellcode-Listings kann der Referenzcode in einem separaten GitHub-Repository eingesehen werden
  • Der Kauf des gedruckten Buchs ist nicht nur eine bessere Möglichkeit zu lesen, sondern hilft auch dabei, die Online-Ausgabe für Leserinnen und Leser aufrechtzuerhalten, denen ein Kauf schwerfällt

Charakter der Online-Ausgabe

  • Data-Oriented Design wird als kostenlose gekürzte Online-Ausgabe zum Thema datenorientiertes Design angeboten
  • Einige nicht zentrale Kapitel wurden ausgelassen, aber der für Lernzwecke nötige Kernablauf ist enthalten
  • Sie richtet sich an Leserinnen und Leser, die einen Ansatz erlernen möchten, bei dem das Design mit Fokus auf die Daten selbst betrachtet wird

Qualität der Dokumentkonvertierung und Code-Referenzen

  • Das Online-Dokument wurde automatisch erzeugt, daher kann die Formatierung ungewohnt wirken
  • Da das Werkzeug zur Konvertierung von LaTeX nach HTML nicht perfekt ist, können Bilder oder Quellcode-Listings beschädigt sein
  • Falls Quellcode-Listings beschädigt sind, kann der referenzierte Code auf GitHub gefunden werden

Gedrucktes Buch und Feedback

  • Das gedruckte Buch lässt sich in einem besseren Format als die Online-Ausgabe lesen
  • Der Kauf des gedruckten Buchs hilft dabei, die Online-Version weiterhin für Leserinnen und Leser verfügbar zu halten, die sich den Kauf nicht leisten können
  • Feedback kann an support@dataorienteddesign.com gesendet werden

1 Kommentare

 
GN⁺ 2023-07-04
Hacker-News-Kommentare
  • Einer der besten Ratschläge, die ich je zum Schreiben von performantem, gut kombinierbarem Code bekommen habe, war: „Arbeite mit Structures of Arrays statt Arrays of Structures“, und dieser Beitrag lässt das stark anklingen.
    Wie sich herausstellte, passt die Entity-Component-Architektur nicht nur zu Spielen, sondern auch zu Business-Anwendungen sehr gut.
    Allerdings sind viele Enterprise-Entwickler im CRUD-Modell der Datensatzverwaltung festgefahren, sodass es ihnen schwerfällt, in Spalten statt in Zeilen zu denken; und die Idee, die Entity-ID in eine published-Tabelle einzutragen, statt ein boolesches Feld published auf true zu setzen, wirkt oft nicht natürlich.
    Wenn man aber einmal erkennt, wie leicht sich dieser Ansatz polymorph erweitern lässt, möchte man ihn auf alle Daten anwenden. Dann entstehen neue Möglichkeiten, Component-Daten übergreifend zu nutzen, und man fragt sich, warum eine Netzwerk-Schnittstelle ein Geburtsdatum hat, eine Rechnung eine IPv6-Adresse bekommt, eine Katze in einem DHCP-Pool landet, limegreen gelöscht wird und dienstags 5 Dollar kostet – aber das ist ja die Hälfte des Spaßes.
    Der Behauptung, dass dieser Ansatz überhaupt nicht zu Objektorientierung passt, stimme ich nicht zu. Ich habe ihn auch mit Rubys Active Record verwendet, und er funktionierte selbst in Bereichen gut, die man normalerweise nicht mit „High Performance“ verbindet. Besonders gut passte es, weil Rubys Objektsystem näher an Smalltalk liegt als an C++/Java und Komposition deutlich stärker bevorzugt als Vererbung.

    • Es kollidiert nicht mit den Mechanismen der Objektorientierung, aber es erfordert, dass Programmierer ihre Sicht auf das Problem ändern.
      In objektorientierten Sprachen konzentriert man sich normalerweise auf ein „Ding, über das man nachdenken möchte“ – etwa einen Nutzer, einen Blogbeitrag oder eine Geldtransaktion –, implementiert es getrennt vom Rest, verbirgt die Daten und überlegt, welche Methoden man anderen Teilen des Systems zugänglich macht. Das Konzept der Kapselung ist sehr stark.
      Beim datenorientierten Design ist es üblicher, dass Daten aus unterschiedlichen Domänen zugänglich sind und Subsysteme sich das herauspicken, was sie für ihre Arbeit brauchen. Java oder Ruby verhindern das nicht, aber für Programmierer gibt es dabei eindeutig eine psychologische Hürde.
    • Der Wikipedia-Artikel „Array of Structure (AoS) and Structure of Arrays (SoA)“ erklärt den Kompromiss zwischen SoA auf der Performance-Seite und AoS bei Intuitivität und Sprachunterstützung: https://en.wikipedia.org/wiki/AoS_and_SoA
      Er behandelt auch Software-Unterstützung, die den Zugriff auf SoA wie auf AoS ermöglicht, etwa Data Frames in R, Pandas in Python oder DataFrames.jl in Julia.
    • In der Datenwelt entspricht eine „Structure of Arrays“ spaltenbasierten Indizes wie bei Snowflake oder OLAP, während ein „Array of Structures“ relationalen Datenbanken mit seiten- und zeilenbasierten Indizes entspricht.
      Ich mag Snowflake sehr und glaube, dass es den anderen Wettbewerbern das Geschäft wegnehmen wird. Interessant ist auch, dass Snowflake Fremdschlüssel „unterstützt“, sie aber nicht erzwingt. Anders gesagt: Snowflake ist genau so viel „NoSQL“, wie ich akzeptieren kann.
    • Meiner Ansicht nach gibt es zwei Arten von datenorientiertem Design. Die eine ist, wie oben beschrieben, der Umgang mit „Structures of Arrays statt Arrays of Structures“.
      Die andere besteht darin, Kapselung aufzugeben, Daten von den Methoden zu trennen, die diese Daten bearbeiten, und die gesamte App danach zu modellieren, wie Daten durch sie hindurchfließen, damit sie leichter zu verstehen und zu ändern ist. Für mehr Korrektheit kann man unveränderliche Datenstrukturen und reine Funktionen einsetzen.
    • Ich habe versucht, ECS auch in Nicht-Spiel-Anwendungen einzuführen, und ein Finanzunternehmen in London hat diesen Rat übernommen, um die Komplexität seiner Systeme zu beherrschen. Es passte einfach wirklich gut.
      Eine sehr kurze Einführung in ECS für Interessierte: https://dev.to/ovid/the-unknown-design-pattern-1l64
  • „Wird die Datenanordnung durch eine einzige Interpretation definiert, die aus einer bestimmten Perspektive stammt?“ könnte aus Sicht von Technologieauswahl und Architektur die wichtigste Frage sein. Um sie zu beantworten, muss man normalerweise mit Business und Kunden sprechen.
    Wenn man sicher ist, dass es genau eine gültige „View“ auf die Daten gibt, die überall verwendet werden kann, ergibt es Sinn, sie im Code festzuschreiben. Wenn man auch nur ein wenig unsicher ist, passt wahrscheinlich ein relationales Modell besser. Viele Unternehmen landen am Ende bei SQL, sobald ihnen die Spieltheorie dieses Problems klar wird.
    Ich frage mich, warum scheinbar alle von einer einzigen großen SQL-Datenbank abgerückt sind. Es gibt zwar „Web-Scale“-Edge-Cases, die die vertikale Skalierbarkeit von Schreibvorgängen gefährden, aber ich glaube, die meisten Unternehmen, einschließlich F100-Unternehmen, werden diese Grenze nie erreichen.

    • In einem früheren F100-Technologieunternehmen gab es die Vorgabe: RDBMS verboten ohne ausdrückliche Genehmigung.
      Das hatte nichts damit zu tun, wie ein bestimmter Datensatz am besten modelliert wird oder welche Lösung die beste Performance bietet, sondern ausschließlich mit Schema-Flexibilität und der Vorgeschichte von Ausfällen durch fehlgeschlagene Schema-Migrationen. Bei NoSQL-Designs traten solche Probleme nicht auf, und die Vorteile einer SQL-Datenbank konnten den großen Vorteil von NoSQL ohne starres Schema nicht aufwiegen.
      Natürlich kann der falsche Einsatz eines Key-Value-Stores Performance und Kosten massiv ruinieren. Auf Cloud-Plattformen wie DynamoDB habe ich viele Fälle gesehen, in denen Daten nicht richtig strukturiert wurden, dadurch massenhaft Scans liefen und die Kosten explodierten.
    • Wir sind nicht vollständig von einer einzigen großen SQL-Datenbank abgerückt, erleben aber eine bestimmte Problemklasse, die mit dieser Architektur zusammenzuhängen scheint.
      Weil es sich um ein altes Großunternehmen handelt, gibt es viele technische Lösungen, die früher von nichttechnischen Mitarbeitenden geschaffen wurden, sich verfestigt haben und weiter gepflegt werden müssen. Es existieren fünf Stufen von SQL-Datentransformationen, angefangen bei der operativen Datenbank bis hin zu Datenmodellen verschiedener Generationen, die jedes Mal entstanden, wenn sich die Art des Geschäfts änderte.
      Je mehr Layer dazukommen, desto weiter wird auf den vorherigen Layern aufgebaut. Wenn eine Anwendung, die vor zehn Jahren auf Abstraktions-Layer 2 gebaut wurde, nun Daten aus Layer 4 braucht, schreibt man ein Skript, das diese Daten in einen früheren Layer zurückführt, und macht weiter. Am Ende ist daraus ein riesiger Klumpen voneinander abhängiger Tabellen und Views geworden, die Daten auf seltsame und wenig intuitive Weise lesen; ein Projekt zur Bereinigung wurde als zu teuer eingestuft und bis in die 2030er-Jahre verschoben.
      Ich verstehe, dass Leute solche Probleme sehen und überlegen, wie man sie hätte vermeiden können. Aus irgendeinem Grund scheint es jedoch unmöglich, Software Engineers die nötige Disziplin aufzuzwingen; man muss irgendwie verhindern, dass überhaupt Spaghetti entstehen können. Hier kommt Entkopplung ins Spiel. Wenn man die Daten anderer Services nicht lesen kann, kann man keine Spaghetti bauen, die beide Seiten ausbremsen.
      Die vertikale Trennung von Anwendungen wird damit zu einer Softwarelösung für das menschliche Problem schwacher Engineering-Disziplin in Unternehmen.
    • Hacker News repräsentiert nicht das gesamte Tech-Ökosystem. Ich denke, die meisten Anwendungen nutzen weiterhin eine einzige große SQL-Datenbank.
      Kürzlich habe ich ein Open-Source-Framework veröffentlicht, das vollständig auf datenorientiertem Design basiert, und ich habe viele Rückmeldungen bekommen, dass dieses Design genau passt. Wenn alle Daten an einem Ort liegen, werden sehr viele Dinge wirklich einfacher.
      https://sql.ophir.dev
    • An den Orten, an denen ich gearbeitet habe, waren die Gründe folgende: Wir sind auf Microservices umgestiegen, eine einzige riesige Datenbank hat die Performance gebremst, und Betrieb sowie Wartung der großen DB waren sehr schwierig.
      In der riesigen DB gab es viele Altlasten, die niemand nutzte und von denen niemand wusste, warum sie existierten, bei denen man sich aber auch nicht sicher war, ob sie nicht doch noch gebraucht wurden; außerdem brauchten Reads und Writes unterschiedliche Optimierungsstrategien.
      Zudem mussten Teams, um sich schnell bewegen zu können, Ownership für Datenbanken und Datenspeicher übernehmen, statt darauf zu warten, dass ein DBA auf ein Ticket reagiert.
    • Ich denke, die Ursache ist dieselbe wie bei der Verbreitung von Microservices und DevOps: Politik wird einfacher.
      Als ich in einem großen, alten Unternehmen arbeitete, waren die meisten Probleme politischer und administrativer Natur. Eine einzige große SQL-Datenbank ist effizient, aber sobald die Organisation, der sie gehört, nicht mit der neuen CTO-Strategie oder einem anderen zentralen Geschäftsbereich übereinstimmt, wird sie zum Problem.
      Kommt dann noch ein Ausfall hinzu, der die geringe Resilienz dieses Modells zeigt, wird daraus schnell ein politisches Ärgernis; selbst wenn die technische Lösung weiterhin allen offensichtlich erscheint, wird ihre Umsetzung schwierig.
  • Dieser Rat ist insgesamt kontextabhängig.
    Spiele haben einfach viele Operationen, die einen spaltenbasierten Ansatz erfordern, aber das gilt nicht für jede Domäne. Best Practices aus dem Spielebereich blind in andere Domänen zu drücken, macht allen nur das Leben schwerer und verschlechtert die meisten Systeme.

    • Es geht nicht nur um den spaltenbasierten Ansatz. Wenn man Daten als Array of Structs organisiert, entstehen Möglichkeiten, Daten effizienter zu packen und den Speicherverbrauch der Anwendung stark zu reduzieren.
      Boolesche Struct-Felder können zu Bitsets werden, nullable Felder zu Sparse oder Dense Maps, und Pointer- oder Referenzfelder zu Integer-Arrays mit kleinerer Breite, die einen Pool indexieren.
      In Umgebungen, in denen die CPU häufig auf Speicherzugriffe wartet, darf man die Wirkung solcher Änderungen nicht unterschätzen. Der Unterschied zwischen L3-Cache- und RAM-Latenz kann ungefähr bei einem Faktor von 10 liegen.
    • Der Rat, häufig genutzte Daten zusammenhängend im Speicher zu halten, gilt auf moderner Hardware für fast alles.
      Für jedes Programm, bei dem Performance auch nur ein bisschen relevant ist, dürfte dies eine der Methoden sein, gute Performance sicherzustellen.
    • Dass Spiele viele Operationen haben, die einen spaltenbasierten Ansatz erfordern, war zum Zeitpunkt der ersten ECS-Ansätze keineswegs offensichtlich. Es hat lange gedauert, Menschen vom objektorientierten Ansatz wegzubewegen und zu überzeugen.
    • Es fühlt sich zunehmend so an, als sei dies die einzige Art, High-Performance-Code zu schreiben.
      Das Einzige, von dem man erwarten kann, dass es auf aktueller Hardware weiter skaliert, ist die Logikdichte. SRAM- und Cache-Größen skalieren mit moderner Lithografie nicht mehr gut, und auch die RAM-Bandbreite ist seit ziemlich langer Zeit nicht mehr stark gestiegen. Die Bandbreite pro Core könnte meiner Meinung nach sogar gesunken sein. Speicherzugriffe sind schon seit einiger Zeit der Flaschenhals.
    • Auch in vielen Codebereichen eines typischen Spiels ist ein spaltenbasierter Ansatz nicht immer richtig; er gilt nur für Teile, die mindestens Tausende von „Zielen“ verarbeiten müssen. Beispiele sind Partikelsysteme oder Navigations- und Kollisionssysteme.
      Datenorientiertes Design ist innerhalb bestimmter Subsysteme sehr sinnvoll, aber für High-Level-Gameplay-Code gilt das, abgesehen von bestimmten Genres, nicht unbedingt.
  • Mike Actons CppCon-2014-Vortrag Data-Oriented Design and C++ halte ich für den besten Programmier-Vortrag, den es bisher gab. Unbedingt sehenswert: https://youtu.be/rX0ItVEVjHc

    • Wirklich hervorragend und auch mein Lieblingsvortrag. Persönlich sehe ich Mike Acton als eine Schlüsselfigur bei der Popularisierung von datenorientiertem Design und ECS-Architektur.
      Früher leitete er auch Unity DOTS, aber leider scheint Unity derzeit ins Wanken geraten zu sein. Die Arbeit an DOTS selbst ist, auch wenn sie unvollendet ist, solide.
    • Wenn man ein Gefühl dafür bekommen will, wie Weltklasse-Performance umgesetzt wird, sollte man sich dieses Video ansehen.
      Ich habe den Großteil meiner Karriere mit dem Schreiben von Web-Apps verbracht, und durch diesen Vortrag habe ich verstanden, „warum jemand C benutzt“.
  • Andrew Kelley hat einen lehrreichen und unterhaltsamen Vortrag darüber gehalten, wie datenorientiertes Design seine Arbeit am Zig-Compiler beeinflusst hat: https://vimeo.com/649009599

  • Auch Anfänger können von Anfang an lernen, datenorientiert zu programmieren.
    Bücher, die diesen Stil Anfängern vermitteln, sind How to Design Programs und A Data-Centric Introduction to Computing.
    https://htdp.org/
    https://dcic-world.org/

    • Diese Bücher sind nicht das, was hier gemeint ist.
  • Ich habe eine Online-Rezension zu dem Buch gefunden: https://gist.github.com/seece/25ed1b2108cf5782718b026382f2c5...

    • Der folgende Satz war interessant und schien dem üblichen Rat zu widersprechen:
      „Die Wurzel allen Übels, die viele Projekte plagt und verzögert, war das Beharren darauf, nicht zu früh zu optimieren. Der Grund, warum Optimierung in späteren Phasen so schwierig ist, liegt darin, dass viel Software so aufgebaut ist, dass überall Objektinstanzen platziert werden, selbst wenn sie nicht nötig sind.“
      Es gibt eindeutig Anwendungen, bei denen Performance oberste Priorität hat, und andere, bei denen das nicht der Fall ist. Das brachte mich dazu, darüber nachzudenken, ob das bedeutet, dass frühe Optimierung bei performancekritischen Apps in Ordnung sein kann. Ich frage mich, ob das die richtige Lesart ist.
      Es gibt auch Data-Oriented Programming: https://www.manning.com/books/data-oriented-programming
      Ich frage mich, ob diese beiden Konzepte dasselbe sind.
  • Datenorientiertes Design ist einsteigerfreundlich. Denn es befasst sich nicht mit Menschen und Business, sondern nur mit der Reinheit der Datenmodellierung.
    Als ich jünger war, bestand der erste Schritt bei einem neuen Projekt darin, ein Entity-Relationship-Modell zu zeichnen, und das wurde zur Grundlage von allem.
    Heute versuche ich, bevor ich mit dem Datenmodell beginne, erst das Problem und die Domäne zu verstehen und über Fähigkeiten sowie darüber nachzudenken, wie man sie bündelt und abgrenzt.

    • Mit Erfahrung merkt man, dass die Liebe zu Daten und Programmierung häufig von Business-Anforderungen zur Seite gedrängt wird.
      Allerdings scheint dieser Text sagen zu wollen, dass, wenn man sich von Anfang an auf das Sammeln von Datenanforderungen konzentriert, die Diskussion über Business-Anforderungen selbst möglicherweise weniger nötig wird.
  • Eines der Kernkonzepte bei DoD ist, Daten nicht hinter Abstraktionen zu verstecken. Es geht eher in Richtung weniger ist mehr.
    Als ich den Einführungstext jedoch schnell gelesen habe, fühlte es sich eher nach dem Gegenteil an. Er redet zu viel und abstrahiert die Kernidee weg. Ich frage mich, ob nur ich es ironisch finde, dass er seinen eigenen Wein nicht trinkt.

  • Der einleitende Absatz ist ziemlich großartig. Die elegante Schreibe und die interessanten Ideen machen Lust weiterzulesen.
    „Daten sind alles, was wir haben. Daten sind das, was wir transformieren müssen, um eine User Experience zu schaffen. Was wir einlesen, wenn wir ein Dokument öffnen, sind Daten. Die Grafik auf dem Bildschirm, der Impuls eines Gamepad-Buttons, die Ursache dafür, dass der Lautsprecher Wellen in der Luft erzeugt, die Art, wie man ein Level aufsteigt, und wie ein Gegner deine Position kennt und auf dich schießt, sind ebenfalls Daten. Die Zeit, die Dynamit zum Explodieren braucht, und die Anzahl der Ringe, die man verliert, wenn man auf Stacheln fällt, sind Daten. Es sind die aktuelle Position und Geschwindigkeit jedes Partikels in der schönen Szene, mit der das Spiel endet; und das, was von der Festplatte gelesen wurde und in dein Leben gelangt ist, ist das Ergebnis von Transformationen durch den Quellcode, den man dem Compiler gefüttert hat, die Anweisungen, die der Assembler ausgegeben hat, und die Maschine, die von den dekodierten Anweisungen angetrieben wird.“

    • Solche Ideen sieht man in der Literatur zu datenorientiertem Design oft, und sie kamen mir immer unnötig reduktionistisch vor.
      Sie können nützlich sein als „kalte Dusche“, um die Bühne zu bereiten und einen aus der Denkweise objektorientierter Abstraktionen herauszuholen. Aber darüber hinaus erscheinen sie mir ungefähr so nützlich, wie wenn ein Ingenieur sagt: „Schau dich um! Alles besteht aus Atomen! Ingenieurwesen besteht im Kern darin, Atome zu bewegen!“
      Das ist nicht falsch, hilft aber bei der tatsächlichen Ingenieursarbeit kaum weiter.