CADS GmbH
Data Oriented Design
Description
Florian Putz von CADS zeigt in seinem devjobs.at TechTalk, wie trotz großer Datenmengen mithilfe von Data Oriented Design doch schnelle Performance von Software erreicht werden kann.
By playing the video, you agree to data transfer to YouTube and acknowledge the privacy policy.
Video Summary
In "Data Oriented Design", Florian Putz of CADS GmbH explains that in data-heavy domains like 3D visualization and simulation, performance hinges on memory access and cache locality: arranging data contiguously and preferring Struct of Arrays over Array of Structs reduces pointer chasing and enables SIMD-style batching. He contrasts OOP’s deep dependencies and shared mutable state with a systems-based approach that queries data on demand, models only temporal dependencies, partitions data, and achieves lock-free multithreading across many cores. Viewers learn when the upfront design effort pays off (large datasets, many cores) and how to apply DOD principles—aligning data layout with access patterns and decoupling systems—to build faster, more maintainable pipelines.
Data Oriented Design for Real-World Performance: Memory Layout, Temporal Dependencies, and Lock-Free Concurrency – A DevJobs.at Recap of “Data Oriented Design” by Florian Putz (CADS GmbH)
Why this talk matters now
In his session “Data Oriented Design,” Florian Putz (Tech Lead and Team Lead at CADS GmbH, part of the KLS Martin Group) tackled a topic that often hides beneath algorithmic discussions but dictates real performance: how we lay out and access data in memory. In medical technology—with 3D visualization, simulations, and large datasets—responsiveness is non-negotiable. Data Oriented Design (DOD) speaks directly to that challenge.
We at DevJobs.at listened closely: Why does data layout make or break modern systems? Why are many “performance problems” really memory problems? And how does DOD deliver not just faster loops, but a different, often sturdier architecture—up to multi-threaded pipelines that run across many cores without a single mutex?
The big idea: Performance is (often) a memory problem
“CPUs are incredibly fast at computation and incredibly slow at reading from RAM,” Florian Putz emphasizes. That observation frames the entire talk: it’s not just the algorithmic complexity—accessing data and moving it through the memory hierarchy is what often burns time.
- L1 to L2 to L3 to RAM: each step away from the CPU comes with sharply higher latency.
- Caches are small and effective—but only if the data you need sits tightly together.
- Result: how your data is organized frequently determines the true performance envelope of your code.
This is the re-centering move behind DOD: treat memory access as a first-class design problem, not an afterthought.
OOP vs. DOD: two different mental models
Putz draws a clear contrast. Object-oriented models are great at expressing relationships and domain logic, but “it does not match how the CPU or the computer actually works.” Hot loops that bounce through object graphs force the processor into pointer-chasing and constant cache invalidations.
- Object-oriented: powerful conceptual modeling, deep ownership chains, but often poor locality where throughput matters.
- Data-oriented: organize data by access pattern. Co-use implies co-location: put values that are processed together adjacently in memory, ideally in continuous blocks.
This shift is conceptual as much as technical. Instead of classes with embedded methods and long-lived references, you get flat data plus systems that, at run time, query exactly the data they need.
Cache locality: the metric that matters
Cache locality ties the story together. If your loop reads values that live consecutively in memory, the CPU can keep its pipelines fed. If relevant values are scattered or padded with fields you don’t currently use, your code “trashes” the cache.
- Avoid pointer chasing: each pointer hop invites a cache miss; aggregate enough small misses and you lose entire orders of magnitude.
- Favor continuous memory: arrays that hold exactly the fields needed for the next step keep the CPU supplied.
- Let compilers do more: when data is packed and regular, compilers can generate wider operations and exploit hardware efficiently.
The win rarely comes from a clever trick inside the loop; it comes from feeding the loop the right bytes in the right order.
Array of Structs vs. Struct of Arrays: the layout decision
The talk contrasts two canonical layouts with tangible consequences:
- Array of Structs (AoS): an array of wide records. Even if the loop only updates positions, the cache still loads velocities, lifetimes, and other fields you don’t need right now.
- Struct of Arrays (SoA): a structure of narrow arrays by field. If you’re updating positions, you iterate a tight array of positions without pulling in unrelated data.
As Putz explains, once your code touches thousands to millions of items per frame, carrying irrelevant fields in and out of cache costs heavily. SoA aligns what you read with what you compute, which reduces cache misses and often enables better compiler optimizations.
Beyond speed: how DOD reshapes architecture
DOD is more than a micro-optimization. Changing how data is structured changes the software architecture around it:
- From hierarchies to systems: instead of deep ownership trees, you have systems that query data on demand—akin to issuing a database query.
- No long-lived references: systems don’t keep pointers to each other or to distant objects. Dependencies are created only at the moment of query and discarded immediately afterward.
- Less shared mutable state: by construction, you reduce side effects and make flows explicit.
The result is a twofold benefit: faster hot paths and cleaner, more maintainable boundaries.
Dependency complexity vs. DOD as a de-coupler
Putz’s description of the “classic” OOP situation will feel familiar: over years, systems accrete opaque webs of dependencies; everything holds a pointer to everything; lifetimes become murky; side effects proliferate.
- Hidden side effects: calls that mutate remote state make bugs slippery and intermittent.
- Difficult lifetimes: who still owns what, and for how long? Untangling references becomes a time sink.
- Multithreading hazards: shared state and locks stuck inside objects invite deadlocks and contention.
DOD counters this by modeling only temporal dependencies. Instead of “Class A knows Class B,” we ask, “What needs to run before what, so the right data is ready at the right time?” That makes ordering explicit without entangling the systems themselves.
Model temporal dependencies: the pipeline as organizing principle
The architectural message is crisp: model time, not entanglement.
- Systems consume inputs and produce outputs; once a system finishes, its transient references vanish.
- The runtime resolves read/write phases implicitly through the system graph.
- The dataflow becomes visible: where values are read and written is governed by schedule rather than by baked-in object relationships.
This visibility makes change safer: when you can point to “read happens here, write happens there,” you can reason about concurrency and refactors confidently.
Concurrency without locks: partition, don’t contend
The standout moment in the talk is the real-world report: “Fully multithreaded software that uses all 32 cores—and there isn’t a single mutex.” The path there is structural:
- Partition data: each job/system operates on a disjoint slice.
- Resolve temporal dependencies: the system pipeline exposes what can run in parallel and what must be ordered.
- Eliminate shared state: without shared mutable objects, there’s no reason to lock. At most, jobs wait on futures.
The payoff: “Concurrency becomes trivial” in many cases—not because threading is easy, but because the data model avoids conflicts at the root.
Where DOD shines—and where it doesn’t
Putz is clear: DOD isn’t a universal hammer. It shines where data volume and throughput dominate:
- 3D engines and rendering
- Simulations
- Data analysis with large datasets
- Gaming
In these domains you get the trifecta: better cache use, higher CPU utilization, and robust concurrency. Conversely, in smaller or less performance-sensitive systems, the initial design overhead may outweigh the benefits.
Costs and the learning curve: what teams should expect
The session does not gloss over the transition cost:
- More upfront design effort: arriving from the OOP world entails a mental reset. Solutions can feel “completely unintuitive” at first.
- Debugging and tooling shift: practices tuned for object graphs don’t map one-to-one.
- New mental models: the center of gravity moves from “objects and relationships” to “data and flows.” Architecture reviews, tests, and discussions all change accordingly.
The reward is tangible: “better cache use, better CPU use, higher throughput … concurrency becomes trivial.” Just as valuable, the dataflow becomes explicit—making change and reasoning easier.
Changeability as a feature: plug systems in and out
A particularly practical advantage is modularity in the small. Putz highlights that you can remove an individual system and the rest of the application continues to function. The example: remove the physics system and physics stops working, but rendering and other systems keep going. In classic OOP, removing a class often prevents compilation altogether or shatters runtime behavior.
This modularity is the direct outcome of clean data separation and modeling only temporal dependencies.
Team playbook: how to think DOD from day one
From the talk, we distilled a set of guiding questions for projects and redesigns:
- What data do we actually touch per frame/iteration? Which parts are reads, which are writes?
- Which fields are co-accessed and therefore belong adjacent in memory? Can we place them contiguously?
- Where do persistent dependencies hide? Can we replace them with temporal ordering?
- How do we partition data so jobs can run without locks?
- Which responsibilities can be phrased cleanly as “consume A, compute B, write C”—without long-lived references?
These questions force formalization of dataflows—a necessary step for effective DOD.
Practical path: from hot loops to system pipelines
The journey typically unfolds in two layers:
- Local optimization: profile hot loops dominated by memory access; separate frequently used fields; adopt Struct of Arrays where appropriate; align iteration with access.
- Global organization: define systems that query inputs on demand; schedule them to reflect temporal dependencies; enable parallel execution where no conflicts exist.
The second layer is transformative: it changes not only runtime speed but also how teams reason about responsibility, testability, and change.
Avoiding misconceptions: what DOD is not
A few non-goals emerge clearly from the session:
- DOD is not automatic: it’s a design discipline. Without intentional data modeling, the benefits won’t show.
- DOD is not dogma: “A hammer is a hammer and a shovel is a shovel.” Use it where it fits.
- DOD is not a bag of micro-tricks: the primary gain is locality, throughput, and architectural clarity—not a single clever instruction in a tight loop.
A quick checklist: is DOD a fit?
- High per-frame/iteration data volume (thousands to millions of items)
- Noticeable stalls despite “good” algorithms
- Profiles show cache misses and pointer-chasing
- Concurrency complicated by locks and contention
- Need to enable/disable systems without breaking the whole application
If several items resonate, DOD likely has a natural foothold.
Quotes and design maxims to carry forward
“CPUs are fast at compute and slow at loading.”
“Group data by how it will be accessed.”
“Between systems, dependencies are implicit—you model only temporal dependencies.”
“All 32 cores, and not a single mutex.”
These are more than slogans—they’re a design compass.
Conclusion: fewer hidden ties, more visible flow—and robust performance
Florian Putz’s “Data Oriented Design” (CADS GmbH) distills a practical truth: in data-heavy software, memory access sets the pace. When we organize data to match how it’s processed, we win twice: raw speed in hot paths and architectural clarity at the system level. Systems decouple. Concurrency becomes plan-driven and often lock-free. The dataflow is visible—and changeable.
Not every application needs DOD. But where performance and throughput matter, it pays to revisit layout, cache locality, temporal dependencies, and partitioning. That shift turns many “performance bugs” into solvable architecture questions—and addresses them at the root.
Key takeaways for engineering teams
- Treat memory access as a first-class concern; layout often beats clever logic.
- Prefer Struct of Arrays when loops touch only a subset of fields.
- Replace deep hierarchies with systems that query data on demand.
- Model time, not permanent relationships—temporal ordering over coupling.
- Partition data to enable lock-free concurrency.
- Apply DOD where data scale and throughput dominate.
Master these principles, and you move from “fast code” to “scalable systems”—exactly the arc Florian Putz charted in his talk.
More Tech Talks
CADS GmbH From Figma to Implementation
Julian Zauner von CADS zeigt in seinem devjobs.at TechTalk welche Überlegungen hinter den grundlegenden Design Elementen in der Software stecken.
Watch nowCADS GmbH Building Products with Purpose
Lukas Reinauer von CADS spricht in seinem devjobs.at TechTalk wie das Unternehmen das Thema der Produktentwicklung organisatorisch angeht.
Watch now
More Tech Lead Stories
CADS GmbH Dominic Koch, Product Manager bei CADS
Product Manager bei CADS Dominic Koch erzählt im Interview über die Abläufe im Unternehmen, was Neueinsteiger erwartet und mit welchen Technologien gearbeitet wird.
Watch nowCADS GmbH Lukas Windner, Division Manager Quality Engineering bei CADS
Division Manager Quality Engineering bei CADS Lukas Windner gibt im Interview einen Überblick über das Recruiting sowie Onboarding und spricht über den Aufbau der Teams und mit welchen Technologien gearbeitet wird.
Watch now
More Dev Stories
CADS GmbH Katharina Freinschlag, 3D Software Entwicklerin bei CADS
Katharina Freinschlag von CADS spricht im Interview über ihren Weg zur Software Entwicklung, welche Challenges im 3D Development gibt und was ihrer Meinung nach Wichtig für Beginner ist.
Watch nowCADS GmbH Claudia Wittner, Researcher bei CADS
Claudia Wittner von CADS redet in ihrem Interview über die ersten Berührungspunkte mit dem Programmieren bis hin zur aktuellen Arbeit, wie ihr Alltag als Researcher aussieht und gibt Tipps für Anfänger.
Watch now