The stereotypes of UI/UX-focused and performance-f...
# thinking-together
a
The stereotypes of UI/UX-focused and performance-focused programmers tend to be somewhat at odds, but I'm starting to optimistically think that they may not be so diametrically opposed... I just finished reading the book 'Data Oriented Design: Software Engineering for Limited Resources and Short Schedules' (of which the author has a free online copy here: http://www.dataorienteddesign.com/dodbook/) and I was struck by a few of his recommendations related to this group (there's definitely more, but these are the things at the top of my head atm): 0) (for a bunch of performance reasons, data are better considered as collections rather than single objects - or even objects at all) 1) Despite their initial appeal, the paradigm of 'objects' falls short in a number of ways. 'Relations' map more consistently between human concepts and computer implementation, are simpler (and so are easier to debug), and typically faster to do computations with. 2) Relatedly, it's generally a good idea to lay out data similar to a normalized relational database - this kept making me think of Eve (@ibdknox were you at all aware of/influenced by the DOD 'movement'/approach?) 3) 'Existence-based' programming (see the chapter of a similar name) reduces a lot of boilerplate noise and eliminates-by-design the possibility of a few classes of errors 4) A mixture of queues and hook/subscription/reactions slot in nicely with the paradigm. This leads to easy concurrency with effective immutability without the mental and CPU overhead of mutexes.
👍 1
i
Very much so. 🙂 In practice, focusing on data layout and on trying to use arrays over most other structures made a huge difference in performance.
We tried this out in lots of domains and got really exciting numbers compared to systems that were built more traditionally.
At the end of the day though, we eventually found that the only way to go fast is to just not do much. 😉
A lot of the fancy data structures and crazy asymptotics you get out of neat algorithms are often completely destroyed by constant factors. More often than not, we found things that looked more like doing stuff on arrays outperformed everything else by fairly significant margins. Even if they were slower "in theory."
💡 1
g
As a game programmer I'm acutely aware of these perf issues but my impression is for the most part they are at odds with easy to use, easy to maintain, easy to understand code. Especially for inexperienced people, the type of people @stevekrouse seems to be targeting. Most people I would think see their data on people as
Copy code
class Person {
   string name;
   string address;
   string phone;
}
not as
Copy code
string[] PhoneNumbers;
string[] Names;
string[] Addresses

class Person {
   int nameNdx;
   int addressNdx;
   int phoneNumberNdx;
};
Probably a bad example but hopefully you get my point. I'm sure systems exist to make things look more like the former but under the hood act like the latter. In fact [Unity's Entity Component System](https://unity.com/unity/features/job-system-ECS) is one such system. But usage is still far more involved than the more obvious method. If I'm not making sense what I'm trying to say is that organizing around perf is mostly a topic for experienced programmers. Another maybe good example is three.js, it started with Vertex objects, each object holding 3 values. You'd make arrays of them then make Face objects and add Vertex objects to do those to make polygons. That's arguably the most obvious idea and when three.js was mostly a software renderer it worked. But then as they added WebGL they ran into the issue that the GPU needs the data all laid out in nice parallel arrays so they have this issue where they currently have 2 paths. Path 1, the old path, Use Vertex and Face, and then the library has to convert to a GPU friendly format anytime data is changed. Path 2, build GPU friendly formats directly, no intermediate format. The problem with Path 2 is for inexperienced programmers they have to deal with data as individual numbers in an array. In other words, to a specific vertex in path 1 could be as simple as
Copy code
const vertex = vertices[vertexIndex];  // easy
where as the GPU friendly way is more like
Copy code
const offset = vertexIndex * stride;
const x = vertices[offset + 0];
const y = vertices[offset + 1];
const z = vertices[offset + 2];
const vertex = new Vertex(x, y, z); // because you want access to vertex methods these 3 values need to be assign a type.
That looks trivial to an experienced programmer but not to a beginner. Anyway, there are probably ways to solve that type of issue and give both perf and easy to follow code for a beginner but I haven't seen any.
s
I think another option for inexperienced programmers is to add a layer of constraints that makes it very hard or impossible to write non-performant code. At least in some axes. of course. its always possible to do too much work or do redundant work, but even that can be a constraint (treat performance as an economy and gamify it a little bit)
a
@ibdknox heh that's a fun connection. My understanding was that Eve was made with web tech (JS at some point in the stack?). Did you do any tests with a native compiled language (e.g. C)? I'd be curious to see the difference. @gman Thanks for the fleshed-out example. It wouldn't surprise me if there are more comprehensible ways of representing it. Eve seems to have made strides in one possible direction in that area. Given people's familiarity with Excel, table columns and rows should be a relatively simple sell. For your example, you could also write it as:
Copy code
class People {
	string[] phoneNumbers;
	string[] names;
	string[] addresses;
}
which is not too dissimilar from your original layout. If you squint a bit, you can see the members as the column headers of a table called People...
👍 1
@Scott Anderson interesting idea, but possibly difficult to implement in the general case... do you have any constraints in mind that might be helpful here? I think that making performance more tangible could help - probably by allowing profiling with trivial difficulty and connecting that to the source/data in a fairly immediate way... (I'm aware that I'm speaking in too many generalities here!)
s
@Andrew Reece. I'm thinking having users write SPMD programs by default, take away their ability to iterate over collections and treat all code as kernels that operate on smallish heterogenous arrays of data (the language can convert everything to SoA if necessary). pixel and vertex shaders do that already (especially material editors in AAA game engines), so do visual particle system (unity vfx and niagra) and machine learning\scientific computing frameworks kind of do it. All of these environments are heavily constrained, and its still possible to make things that perform horribly, or perform well in isolation and poorly in production. I think its possible to build a pretty robust simulation framework\game engine type thing that encourages high performance, even if its constrained in certain ways
More reference, info about Bungie's TFX shader system\bytecode intepreter referenced in the particle system presentation http://advances.realtimerendering.com/destiny/gdc_2017/Destiny_shader_system_GDC_2017_v.4.0.pdf
i
@Andrew Reece we wrote versions of Eve in lots of different languages (TS, Clojure, Rust, C, Go, ...), but this pattern makes just as much difference in JS as it does anywhere else. Rust ended up being the fastest by a good margin.