3 ms·
Quote from the linked article by John Carmack[1]: > The fly-by-wire flight software for the Saab Gripen (a lightweight fighter) went a step further... Control
by wolfgang42 10y ago
Quote from the linked article by John Carmack[1]:
> The fly-by-wire flight software for the Saab Gripen (a lightweight fighter) went a step further... Control flow went forward only. Sometimes one piece of code had to leave a note for a later piece telling it what to do, but this worked out well for testing: all data was allocated statically, and monitoring those variables gave a clear picture of most everything the software was doing.... No bug has ever been found in the “released for flight” versions of that code.
When I started writing Arduino code, I independently re-invented this technique. I write my code with only fixed-size loops and no delay() calls (basically cooperative multitasking), making heavy use of finite-state machines to keep track of what should happen when.
This style of code takes some getting used to, but its advantages are enormous: I see other people using delays and busy-loops and then struggling to get interrupts working to keep their device responsive, whereas I have a clean linear set of logic that can be easily understood and is free of strange race conditions and the like, and is guaranteed to keep responding to events.
This style also makes it easy to literally eyeball performance: attach a bicolor LED (one that has e.g. red and green LEDs in the same package) and tell it to toggle colors once per loop. If the main loop is taking more than 8 milliseconds or so the LED will start to flicker visibly; if something pauses the LED will go solid and it's obvious the main loop is frozen.
[1] http://number-none.com/blow/blog/programming/2014/09/26/carmack-on-inlined-code.html http://number-none.com/blow/blog/programming/2014/09/26/carm...
(Edits for clarity and writing style.)
- dahart 10y agoOne of the interesting side effects of this style is that you sometimes choose to let code run slower than it could, and choose to use more memory than you need. The point is (as you say) to make all loops & allocation as predictable as possible, so when you make them fixed size, you have to fix it on the worst case. Ideally there is no worst case, and the amount of work you do per frame or cycle is constant. But for anything non-trivial, chances are fixed allocations & loops aren't always needed, even though they're extremely useful. This does exactly what you say, in my experience: it makes performance eyeball-able, you can see where problems are. Code becomes so easy to reason about that debugging is easier and time is saved.
- RangerScience 10y agoI would like to see more of this style of code (specifically in the Arduino setting) as I'm having trouble seeing what you're up to from here. Is some place I can read more - ideally, actual code?
- wolfgang42 10y agoMost of the code I've written either can't be released for privacy reasons (I don't feel like scrubbing out the info of the person I wrote it for) or is weird one-off experimental code that's a pain to explain. However, I did find one standalone project that illustrates the point quite elegantly; I've just written up some documentation and posted it on https://github.com/wolfgang42/iDropper-arduino https://github.com/wolfgang42/iDropper-arduino This code cheats a little bit in that it has some delay loops in it; this is because the timings are finicky and it was a lot easier to write this way. Notice, however, that the `idrop_loop()` function that drives everything still specifies a four-millisecond maximum runtime, far under anything that I've ever needed to worry about. Let me know if you have any questions about this; I feel that some of the explanation I wrote isn't quite as clear as it should be, and because the code is so minimal (it's really more of a library than a full project) it doesn't illustrate the point quite as well as I'd like.
- dahart 10y agoI don't have any examples to share, but I'll add that the thinking behind this style is sometimes codified by style guides for projects that requires high levels of code safety. The best example I can think of is the famous "Power of Ten" rules for code safety published by NASA. Follow these rules, and the byproduct will be the kind of code we're talking about. http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf http://pixelscommander.com/wp-content/uploads/2014/12/P10.pd...
- z3t4 10y agoThanks for sharing the link. In JavaScript you can put functions inside functions, so if it's only used once you can put it where it's used, witch would have the same effect as in-lining it. But you also get to eat the cookie as you get the advantage of using functions. I like the advice of setting a breakpoint and then stepping though all the code for example a frame. If what actually happens is way off from how the code is structured your team will have problems comprehending what the code does, witch will make it very hard to work with.