Live data from Hacker News

John Carmack on inlined code (2014)

number-none.com

191–200 of 402 posts

Re: John Carmack on inlined code (2014)

#191
post #2

When I first heard the maxim that an intelligent person should be able to hold two opposing thoughts at the same time, I was naive to think it meant weighing them for pros and cons. Over time I realized that it means balancing contradictory actions, and the main purpose of experience is knowing when to apply each. Concretely related to the topic, I've often found myself inlining short pieces of one-time code that mad…

Wait, isn't that just Doublethink from 1984? Holding two opposing thoughts is a sign that your mental model of the world is wrong and that it needs to be fixed. Where have you heard that maxim?

No you've got it completely backwards. Reality has multiple facets (different statements, all of which can be true) and a mental model that insists on a singular judgement is reductionist, missing the forest for the trees. Light is a wave and a particle. People are capable of good and bad. The modern world is both amazing and unsustainable. etc.

Holding multiple truths is a sign that you understand the problem. Insisting on a singular judgement is a sign that you're just parroting catchy phrases as a short cut to thinking; the real world is rarely so cut and dry.

Re: John Carmack on inlined code (2014)

#192
post #57

His overall solution highlighted in the intro is that he's moved on from inlining and now does pure functional programming. Inlining is only relevant for him during IO or state changes which he does as minimally as possible and segregates this from his core logic. Pure functional programming is the bigger insight here that most programmers will just never understand why there's a benefit there. In fact most programme…

Some grasp it but see its trade-off contract, which is demanding.

With practice it just becomes another paradigm of programming. The trade off is really a skill issue from this perspective.

The larger issue is performance which is a legitimate reason for not using fp in many cases. But additionally in many cases there is no performance trade off.

Re: John Carmack on inlined code (2014)

#193

Here are some information theoretic arguments why inlining code is often beneficial: https://benoitessiambre.com/entropy.html In short, it reduces scope of logic. The more logic you have broken out to wider scopes, the more things will try to reuse it before it is designed and hardened for broader use cases. When this logic later needs to be updated or refactored, more things will be tied to it and the effects will b…

This is why I think it's a mistake that many popular languages, including standard c/c++, do not support nested function definitions. This for me is the happy medium where code can be broken into clear chunks, but cannot be called outside of the intended scope. A good compiler can also detect if the nested function is only called once and inline it.

Re: John Carmack on inlined code (2014)

#194
post #79

His overall solution highlighted in the intro is that he's moved on from inlining and now does pure functional programming. Inlining is only relevant for him during IO or state changes which he does as minimally as possible and segregates this from his core logic. Pure functional programming is the bigger insight here that most programmers will just never understand why there's a benefit there. In fact most programme…

Here's the link where he discusses functional programming style: https://web.archive.org/web/20170116040923/http://gamasutra.... He does not say that that his email is completely outdated - he just says that calling pure functions is exempt from the inlining rule. He's not off writing pure FP now. His approach is still deeply pragmatic. In the link above he discusses degrees of function purity. "Pure FP" has a whole…

He literally said he’s bullish on pure fp. Which means he is off writing pure fp. His own article about it never explicitly or implicitly implies a “pragmatic approach”.

I never said he said his email was completely outdated. He for sure implies it’s outdated and updates us on his views of inlining which I also mentioned.

Re: John Carmack on inlined code (2014)

#195

His overall solution highlighted in the intro is that he's moved on from inlining and now does pure functional programming. Inlining is only relevant for him during IO or state changes which he does as minimally as possible and segregates this from his core logic. Pure functional programming is the bigger insight here that most programmers will just never understand why there's a benefit there. In fact most programme…

> he's moved on from inlining and now does pure functional programming Neither of those are true. He does more FP ”where reasonable“, and that decreases the need for inlining. He does not do pure FP, and he still inlines.

He literally says he’s more bullish on pure fp. Read it. And I also wrote about where he still inlines.

Re: John Carmack on inlined code (2014)

#196
post #2

When I first heard the maxim that an intelligent person should be able to hold two opposing thoughts at the same time, I was naive to think it meant weighing them for pros and cons. Over time I realized that it means balancing contradictory actions, and the main purpose of experience is knowing when to apply each. Concretely related to the topic, I've often found myself inlining short pieces of one-time code that mad…

My intro to programming was that I wanted to be a game developer in the 90s. Carmack and the others at Id were my literal heroes.

Back then, a lot of code optimizations was magic to me. I still just barely understand the famous inverse square root optimization in the Quake III Arena source code. But I wanted to be able to do what those guys were doing. I wanted to learn assembly and to be able to drop down to assembly and to know where and when that would help and why.

And I wasn't alone. This is because these optimizations are not obvious. There is a "mystique" to them. Which makes it cool. So virtually ALL young, aspiring game programmers wanted to learn how to do this crazy stuff.

What did the old timers tell us?

Stop. Don't. Learn how to write clean, readable, maintainable code FIRST and then learn how to profile your application in order to discover the major bottlenecks and then you can optimize appropriately in order of greatest impact descending.

If writing the easiest code to maintain and understand also meant writing the most performant code, then the concept of code optimization wouldn't even exist. The two are mutually exclusive, except in specific cases where it's not and then it's not even worth discussing because there is no conflict.

Carmack seems to acknowledge this in his email. He realizes that inlining functions needs to be done with careful judgment, and the rationale is both performance and bug mitigation. But that if inlining were adopted as a matter of course, a policy of "always inline first", the results would quickly be an unmaintainable, impossible to comprehend mess that would swing so far in the other direction that bugs become more prominent because you can't touch anything in isolation.

And that's the bane of software development: touch one thing and end up breaking a dozen other things that you didn't even think about because of interdependence.

So we've come up with design patterns and "best practices" that allow us to isolate our moving parts, but that has its own set of trade-offs which is what Carmack is discussing.

Being a 26 year veteran in the industry now (not making games btw), I think this is the type of topic that you need to be very experienced to be able to appreciate, let alone to be able to make the judgment calls to know when inlining is the better option and why.

Re: John Carmack on inlined code (2014)

#197

I think the major problem with this is scope. Now a variable declared at the top of your function is in scope for the entire function. Limiting scope is one of the best tools we have to prevent bugs. It's one reason why we don't just use globals for everything.

You can artificially create scope. I often write code like: Foo f = null; { ... stuff with variables f = barbaz; }

Now you have to make `f` nullable and you run the risk of not initialising it and getting a null pointer.

You can't do it in C, but in functional style languages you can do this:

  let f = {
    let bar = ...;
    let baz = ...;
    let barbaz = ...;
    barbaz
  };
Which is a lot nicer. But if you ask me it's just a function by another name except it still doesn't limit scope quite as precisely as a function.

Re: John Carmack on inlined code (2014)

#198

Earlier quoted context omitted.

It might be a significant problem, but not in the code, but the compiler. Fair enough, you are working around a compiler issue.

If you consider any superlinear complexity a 'compiler issue' I guess.

It absolutely is, if it makes compile times unreasonable for reasonable code. Compilers have to make trade-offs like this all the time, they can't use overly excessive optimizations.

Re: John Carmack on inlined code (2014)

#199

Earlier quoted context omitted.

Well there's also compiler directives other than `inline`, like msvc's `__inline` and `__forceinline` (which probably also have an equivalent in gcc or clang), so personally I don't think you need to make the tradeoff between readability and reusability while avoiding function calls. Not to mention C++ constevals and C-style macros, though consteval didn't exist in 2007

__forceinline is purely a suggestion to the compiler, not a requirement. Carmack's point isn't about optimizing the costs of function calls though. It's about the benefits to code quality by having everything locally visible to the developer.

It's an interesting view because I find neatly compartmentalized functions easier to read and less error prone, though he does point out that copying chunks of code such as vector operations can lead to bugs when you forget to change some variable. I guess it depends on the function. Something like

    Vector c = dotProduct(a, b);
is readable enough and doesn't warrant inlining, I think. There's nothing about `dotProduct` that I would expect to have any side effects, especially if its prototype looks like:

    Vector dotProduct(Vector const& a, Vector const& b) const;

Re: John Carmack on inlined code (2014)

#200
post #161

I have a coworker that LOVES to make these one or two line single use functions that absolutely drives me nuts. Just from a sheer readability perspective being able to read a routine from top to bottom and understand what everything is doing is invaluable. I have thought about it many times, I wish there was an IDE where you could expand function calls inline.

Sometimes it's easier to define some vocabulary and then use it. Like defining push and pop on a stack vs stack[++ix] = blah and blah = stack[ix--].

And avoids needing to think about it being prefix or postfix after you don't that one time.

But at other times it's insufferable, when the abstraction is leaky and unintuitive.

Post reply on HN