31 ms·
This reminds me of a portion of a talk Jonathan Blow gave[1], where he justifies this from a productivity angle. He explains how his initial implementation for
by nlawalker 7mo ago
This reminds me of a portion of a talk Jonathan Blow gave[1], where he justifies this from a productivity angle. He explains how his initial implementation for virtually everything in Braid used arrays of records, and only after finding bottlenecks did he make changes, because if he had approached every technical challenge by trying to find the optimal data structure and algorithm he would never have shipped.
"There's a third thing [beyond speed and memory] that you might want to optimize for which is much more important than either of these, which is years of your life required per program implementation." This is of course from the perspective of a solo indie game developer, but it's a good and interesting perspective to consider.
[1] https://www.youtube.com/watch?v=JjDsP5n2kSM https://www.youtube.com/watch?v=JjDsP5n2kSM
- Insanity 7mo agoIt's easy to see this outside of the perspective of a solo game developer. We all have deadlines to manage even in the regular 'corporate world'. And engineering time spent on a problem also translates to an actual cost. It's a good consideration tbh.
- dgb23 7mo agoIt's also notable that video games are programs that run for hours and iterate over large sets of very similar entities at 60 frames or more per second repeatedly and often do very similar operations on each of the entities. That also means that "just do an array of flat records" is a very sane default even if it seems brutish at first.
- quietbritishjim 7mo agoI think when he said "just do an array of flat records" he meant as opposed to record of arrays (i.e. row oriented vs column oriented), as opposed to fancy data structures which I think you're assuming he was implying. Separate arrays for each data member are common in game engines exactly because they're good for iterating over, which as you said is common.
- O3marchnative 7mo agoThat's also great for letting the compiler unlock auto-vectorization opportunities without delving into the world of manual SIMD. Even storing something simple such as an array of complex numbers as a structure of arrays (SoA) rather than an array of structures (AoS) can unlock a lot of optimizations. For example, less permutes/shuffles and more arithmetic instructions. Depending on how many fields you actually need when you iterate over the data, you prevent cache pollution as well.
- mabster 7mo agoI haven't watched his videos on his language for ages, but this was a big thing he wanted in his language: being able to swap between array-of-structs and struct-of-array quickly and easily.
- MaxBarraclough 7mo agoJonathan Blow's own unreleased Jai programming language has a feature to make it trivial to switch between array-of-structs and struct-of-arrays. From a quick search, it seems HackerNews's own jcelerier has put together a C++ library for doing this. https://github.com/celtera/ahsohtoa https://github.com/celtera/ahsohtoa
- wild_egg 7mo agoZig also makes this trivial
- deleted 7mo ago[deleted]
- throwaway2037 7mo agoI believe you. Can you provide a simple example? I would be helpful for me to understand.
- arendtio 7mo agoI would like to add that Braid is not a normal video game. To me, it is a piece of art. It contains so many mind-bending mechanics that I think it is a real possibility that you could have worked on some of that stuff for years, making it unlikely to ship at all. So, in addition to the performance requirements of a video game, Jonathan also had to find ways to implement all those fancy mechanics.
- skeeter2020 7mo agoI'd be careful extending learnings from games (solo or team efforts) to general programming as the needs and intent seem to be so different. We rarely see much code re-use in games outside of core, special-purpose buy largely isolated components and assets. Outside of games there's a much bigger emphasis on the data IME, and performance is often a nice-to-have.
- awesome_dude 7mo agoYeah - A game is (generally) a one and done enterprise. Like a start up it's all about getting it out the door, there's little to no expectation of having to maintain it for any real length of time.
- fidotron 7mo agoHN has some hot takes but that one is particularly impressive. Fortnite, Roblox, League of Legends, Counter Strike . . . all very short term projects.
- wat10000 7mo agoFor every game like that, there are a thousand games that shipped, maybe got a few updates, and then they were done.
- awesome_dude 7mo agoWe can probably add to that the fact that the nominated titles almost certainly started out with spaghetti code that had to be refactored, reworked, and gave maintainers nightmares in their sleep
- jjmarr 7mo agoRoblox didn't have server functions until 2014 and they weren't mandatory until 2018. Anything the client did automatically replicated to every other client. That meant I could attach Cheat Engine to Roblox, edit memory addresses to give myself in-game cash, and inject whatever code I wanted to everyone else. Thankfully it was sandboxed so I couldn't give people viruses. This was probably a good decision because most of Roblox's best games from that period weren't updated to use server functions. It's too difficult.
- suzzer99 7mo ago> how his initial implementation for virtually everything in Braid used arrays of records This is me with hash maps.
- Fraterkes 7mo agoThis is slightly surprising to me, since Braid is kinda infamous for being in development for a pretty long time for a puzzle platformer
- SatvikBeri 7mo agoWas 3 years a long time for an indie platformer in the early 2000s? Looking at some similar examples: * Braid was 3 years * Cave Story was 5 years * World of Goo was 2 years * Limbo was about 3 years (but with 8-16 people) So Braid seems pretty average.
- Fraterkes 7mo agoYeah, you’re right. I must’ve misremembered.
- YesBox 7mo agoWow! I'm shocked Limbo took 3 years and had a larger team. I've played a bit of the game (but didn't complete it). Looking at the Steam reviews and a quick search shows me it takes 3-10 hours to beat the game. :O
- GuB-42 7mo agoIIRC the Limbo team grew over time, it shows in gameplay, the second half feels less personal and more like a generic platformer. They hired more people to get done with it. It don't mean it is rushed, but to me, the second half lacks personality compared to the first half. Also, I don't like the idea of using gameplay time as a value statement. Maybe I say that because I don't have money problems, but I find that the tendency certain gamers have of judging games in terms of dollars per hour of gameplay is pretty damaging, as it incentivizes developers to focus on gameplay time more than polish. 3-10 hours is already plenty for that style of game. Note that there are many AAA games in the 10 hour range.
- IshKebab 7mo agoI feel like a game is a bit different though because you control the input. You can't profile input you've never seen.
- gowld 7mo agoJonathan blow has spent the past 10 years and almost all of his money trying to build the perfect programming language for his 3rd game. Also, Rule 5 contradicts the idea you quoted from Blow.
- parasense 7mo agoThe funny thing is even data structure is really an array of memory depending how low down deep one looks. All the people who took an intro computer science course knows, those who had to implement a heap allocator, it's all really just arrays underneath...
- jasonwatkinspdx 7mo agoThat's very much the norm in the game dev world, especially for someone like Jonathan who's been doing this since the early era of PC gaming. You've got 16 ms to get that next frame rendered, so stuffing everything into fixed sized tables and linear walks is a simple way to structure against that limit. You've got an entity budget of so many, and there's no unpredictable delays from dynamic allocation or similar. Even when using scripting languages that offer more flexibility, like LUA or C#, you see a tendency towards this pattern.