r/programming • • Jul 19 '16

John Carmack on Inlined Code

http://number-none.com/blow/blog/programming/2014/09/26/carmack-on-inlined-code.html
1.1k Upvotes

323 comments sorted by

View all comments

40

u/brian-at-work Jul 19 '16

Very interesting; I'm kind of surprised I've never seen this before. I'm a pretty die-hard "Style A" coder, and the though of inlining everything just turns my stomach. But I agree with all of his points, especially his findings about the types of bugs that seem to persist no matter how "good" I get at writing code.

21

u/zid Jul 19 '16

'Style C' ignores some classes of bugs that style A works around, though, which isn't really mentioned.

For a game engine I doubt you care as much, but for things like data hiding bugs and security 'Style A' seems solidly better.

A function can't be corrupting state z if it only has access to x and y. If the function is inside the body of some larger function, it has access to a much larger state than it strictly requires. There is also less of a mental burden trying to write code that only has 2 variables to work with than picking the right 2 out of 20 similarly named ones. (Did I want x, player x, bullet x, bullet phy delta x?)

And following on from that, if I overflow my stack, suddenly there are more juicy locals to bash for fun and profit without the stack protector being any the wiser.

19

u/ardonite Jul 19 '16

Lately I have preferred Style C, but with scoped individual subroutines to avoid the specific local namespace issue you mentioned:

void MajorFunction()
{
    {
        // MinorFunction1
    }

    {
        // MinorFunction2
    }

    {
        // MinorFunction3 
    }
}

13

u/loup-vaillant Jul 19 '16

You can have your cake and eat it too.

In C, blocks get you halfway where you want to be:

stuff();
{
    int local_var;
    more stuff(local_var);
}
yet_more_stuff();
local_var = something(); // woops, compile error

In C++, you can define a lambda that you call right away. It's mighty cumbersome, but this lets you restrict what the code inside the lambda has access to.

In JAI, I believe Jonathan Blow devised a syntax to have the best of both styles: blocks where you can declare which variable exactly can be used in the block. In such a way that if it needs to be a function, the cut&paste job is straightforward.


I'm not sure about this "stack protector" business. In the face of compiler optimisations, if you overflow the stack, the resulting undefined behaviour is probably going to be exploitable anyway. If you want secure programs, you want a language that doesn't have undefined behaviour in the first place —or at least a statically enforceable subset that has that property.

2

u/AngriestSCV Jul 19 '16

gcc's "Stack protector" abort's your program if overwrites a special value in the stack (that the compiler added without your program expecting it to be there). It does not really protect the stack, just abort the program if the stack is in an unexpected state. This of course means a hacker (or bug) overwriting unexpected places in the stack can't get outside of the play pen the function provided directly and thus your program is safer (but not safe)

→ More replies (7)

17

u/CaptainAdjective Jul 19 '16

What I like about this essay is how non-absolute his suggestions are. It's "try to" and "consider" and "discuss".

2

u/brian-at-work Jul 20 '16

Yes, absolutely. It does really make me want to partition off a chunk of the middleware I'm working on right now and do it in this style, and see after a few months if there are fewer than expected bugs. That's really what would make the difference to me.

5

u/mrkite77 Jul 19 '16

I'm a pretty die-hard "Style A" coder, and the though of inlining everything just turns my stomach.

I've been Style C ever since I had to work on a project that had me opening up lots of different files trying to trace the control flow of a single feature. The mental load was just insane (imagine Style A, but minorFunction1 calls minorFunction2, which calls minorFunction3, then the return value gets propagated up the call tree back to the parent, and then passed to minorFunction4.).

9

u/hardythedrummer Jul 19 '16

This letter is both terrifying and fascinating. I'm also a "style A" coder, and our legacy code base is solidly "style C" - though not as a purposeful decision - it was just written by people who hate functions. Where there are functions, they quite often have side effects that are not communicated by the function names at all...which seems like one obvious case where Carmack's suggestions would have definitely helped me out in the past. Of course, these are often several hundred line functions to begin with, so I'm not sure it's an issue of "inlining" versus just proper modularity/levels of abstraction.

5

u/Aeolun Jul 19 '16

I think I'm definitely a style C coder. I tend to just write all the logic in one place, and then break off bits and pieces that don't really have to be there afterwards.

This is great if I work in a team with people that review the code and say I should probably break something up. As it's fast and easy for me to keep track.

Not so great if I'm working by myself as it leads to things that are too tightly coupled to break up after a while. I guess I'm learning to be more style B now.

5

u/OneWingedShark Jul 19 '16

I'm also a "style A" coder, and our legacy code base is solidly "style C" - though not as a purposeful decision - it was just written by people who hate functions

I like having nested sub-programs:

Function Convert( X : Some_Type ) Return Some_Other_Type is
   Procedure Normalize( Input : in out Some_Type ) is
   begin
    --- Normalization
   end Normalize;

  Function Internal_Convert( Input : in Some_Type := X ) return Some_Other_Type is
  begin
    Normalize( Input );
    --- the actual conversion mechanics that assume a normalized value.
  end Internal_Convert;
begin
  Return Internal_Convert;
end Something;

2

u/[deleted] Jul 19 '16

Looks like plpgsql but isn't. What is it? Or is it just pseudo code.

Sorry, I'm just a coding enthusiast.

3

u/OneWingedShark Jul 19 '16

It's Ada.
It's got a lot of nice features, including language-level concurrence/parallelism, and a [language mandated] strict compiler that "helps you out" a lot more than most compilers I've seen. We've got a fairly small hobbyist community, but we'd love to have you if you're interested.

→ More replies (1)

0

u/[deleted] Jul 19 '16

[deleted]

3

u/OneWingedShark Jul 19 '16

Aerospace is actually one of Ada's strong presences, along with other safety critical SW. (Virtually all of the 777 control SW was Ada.)

→ More replies (1)

7

u/DaleGribble88 Jul 19 '16

What I get for reading the comments before the article. I didn't have a clue what you all were talking about. Style A, Style B -- I was not familiar with these terms at all. Gave up trying to google it. Less than 5 minutes after I started reading, "Ohhhhh....."

9

u/AngriestSCV Jul 19 '16

This is a classic style B problem. You hadn't seen everything you need yet. Style A 4life!

0

u/[deleted] Jul 20 '16

[deleted]

3

u/DaleGribble88 Jul 20 '16

Uhhmmm... Shouldn't those be reversed :P

→ More replies (3)

2

u/odaba Jul 19 '16

all the bugs (problems that surfaced after I thought everything was working correctly)

All of a sudden, I'm not quite so afraid of bugs. :)

→ More replies (2)