Live data from Hacker News

Random Acts of Optimization

engineering.riotgames.com

51–60 of 128 posts

Re: Random Acts of Optimization

#51
post #22

Earlier quoted context omitted.

There is such a thing as profile guided optimization. I don't think their results are particularly impressive. You're basically saying "can't you just" to which the answer is almost always no. No you can't just.

It's not that results are unimpressive, but the market has dictated faster compile times. When a PGO compilation is an order of magnitude slower, for the 90% of applications out there where the extra 5-25% improvement means less than a 60 sec improvement, then you won't care about PGO. You need to have an application an order of magnitude larger (in run time) to care about PGO. Smaller than Google, bigger than your s…

For video games you usually have at least Debug, Release, Retail builds. Where Retail turns on Link Time Code Generation (LTCG) which is quite slow but can give a few percent extra perf. If PGO took 10x to compile but gave a 20% perf boost it'd be an absolute no brainer for game development. Keeping in mind that article shared here was a video game.

It's possible that PGO is pretty awesome these days and people just don't realize it. Just because I've heard unimpressive results from other devs doesn't mean it's actually bad!

Re: Random Acts of Optimization

#52
post #2

>In our case we output the profile buffer to a file and read that into the visualization tool which is conveniently built into Chrome. (You can find more information about the tracing tool here and you can try it out by typing “chrome://tracing/” into your Chrome browser. It is designed for web page profiling, but the format of the input profile data is a simple json format that can be easily constructed from your ow…

Another term for these profiling charts in Chrome is flame charts, you might be able to find even more tools by it.

Re: Random Acts of Optimization

#53

This brings up a thought that I've had for a very long time. Almost every type of optimization that a programmer could employ is repeatable. It involves matching patterns ("Identification" in the context of this article), analysis ("Comprehension"), and rewriting ("Iteration"). All of these steps can be efficiently automated. And it turns out that compiler writers collectively know about the vast majority of these te…

Please show us some of these promised optimizations. I don't think they actually exist. Most of the larger code / algorithm tweaks require subtle changes to the behaviour. The compiler can't choose to do that by itself, as it could break the program. Programmers need to make these choices for themselves.

Besides which, compilers can already select slow or fast optimizations on the command line, so users can minimize compile time if they wish. There are plenty of people who would give anything for faster code, no matter what the compile time is.

Please prove me wrong and explain a few of these supposed too-slow optimizations.

Re: Random Acts of Optimization

#54
post #41

Earlier quoted context omitted.

Insulation from performance concerns also makes your performance model less predictable. Because the ends of optimisations are observable, but their means are not, people resort to “butterfly programming”. As a small example, in ActionScript 3, people used to write their conditionals like this: if (a) if (b) { ... } Rather than this: if (a && b) { ... } Because the dumb compiler generated better code for the former.…

I wonder if it would be practical to expose the optimizations to the programmer and allow the complex ones that are easy to accidentally disable to be invoked explicitly. Your code would look something like: optimization(fold_constant_vector_lookup_access_frobnitz) { complex code here } And if the compiler can't apply the optimization, it can produce an error rather than slow code.

That works. We already have some things like that, like “__attribute__((always_inline))”. Of course, forcing some optimisations could implicitly prevent others, but that’d also be true if you did it manually.

With expressive enough metaprogramming, you could also do some of these explicit optimisations in user code.

Re: Random Acts of Optimization

#56

Hey everyone, I'm the author of this article and I'm glad you've found it interesting. I'll be keeping an eye on this thread, so if you have any questions or comments I'll address them as soon as I can. I can already see some awesome questions here - looking forward to the discussion.

Why scan the table of precomputed values? It seems like the code would be both cleaner and faster like this:

  class AnimatedVariable {
    int numValues;
    std::vector values;
    // ...
  }
Then:

  if (!mPrecomputed) {
    float idx = time * numValues;
    float before = values[idx], after = values[idx+1];
    return lerp(before, after, idx - (int)idx);
  }
I guess there's a bit of float -> int coercion going on there, but it shouldn't be too bad.

Re: Random Acts of Optimization

#57
post #29

Seems they don't want anyone using PIA to access their blog... Tried reconnecting and got denied again, had to switch endpoint country to actually get access. > Error 1008 Access denied. The owner of this website (engineering.riotgames.com) has banned your IP address (108.61.57.217). > Error 1008 Access denied. The owner of this website (engineering.riotgames.com) has banned your IP address (108.61.13.45).

Or that's the end effect of having been attacked from those IP addresses, which I'm assuming are not unique to the user.

Re: Random Acts of Optimization

#58
post #16
post #12

Earlier quoted context omitted.

Riot's code base has a massive amount of technical debt, to a point where a rewrite is likely the best choice because of past technology decisions.

A rewrite would murder them. I'm not going to link that article everyone links about "never rewriting your code", because I don't think it's got the argument right, but I strongly feel that if they tried to rewrite a system as complex as theirs, they would either a) never finish or b) stop developing the game and, by the time they finished their rewrite, have no customers left. Anyway, it would end up being called a…

I came to a deeper understanding of this problem earlier this year.

A team that 'made a mess' may think they know all the mistakes they have made in the code, but they have never proven it, and they haven't been practicing doing things 'the right way'. They haven't even learned how to push back on bad strategic decisions that made things worse.

How do you know that the rewrite will be profoundly better than the current version? I think you have rather a lot of evidence that it won't.

Take a team that cleans up their messes as they go. They know whether their new ideas are better or worse. They have proven they 'deserve' a better code base by building one. By the time they know for sure what's really wrong with the code, they no longer need a complete rewrite. They need a partial rewrite that they can string out over the course of a couple years.

If any of that is true, then the people who want a do over won't take advantage of it, and those that would benefit most wouldn't feel comfortable doing it.

Re: Random Acts of Optimization

#59

This brings up a thought that I've had for a very long time. Almost every type of optimization that a programmer could employ is repeatable. It involves matching patterns ("Identification" in the context of this article), analysis ("Comprehension"), and rewriting ("Iteration"). All of these steps can be efficiently automated. And it turns out that compiler writers collectively know about the vast majority of these te…

Please show us some of these promised optimizations. I don't think they actually exist. Most of the larger code / algorithm tweaks require subtle changes to the behaviour. The compiler can't choose to do that by itself, as it could break the program. Programmers need to make these choices for themselves. Besides which, compilers can already select slow or fast optimizations on the command line, so users can minimize…

Not the OP, but one I think about a lot is converting functional, monadic code that uses first class functions/closures to equivalent imperative variants.

For example, manipulating collections with functions like map, flatMap, filter, etc. has become common, even in popular imperative languages like C# and Java. These calls are can be chained together to create non-strict sequences (IEnumerable, Stream, etc.) which are made strict at a later time. Each call creates a new sequence, and many take closures. Both of these require memory allocation and indirect dispatch.

However, in many cases it extremely straightforward to convert these into loops. For example, the following C# code:

    list.Select(f).Where(p).SelectMany(g).ToList()
Could be turned into:

    var outList = new List();
    foreach(var x in list) {
      var y = f(x);
      if(!p(y))
        continue;
      foreach(var z in g(y)) {
        outList.Add(z)
      }
    }
This works, even if we known nothing about f, p, and g (e.g. they can be impure functions). This optimization is especially effective if these functions are lambdas. It is also always going to be faster and safe; the only difference is that we removed a series of extra allocations and indirect function calls. This example is admittedly simple, but many functional patterns and behaviors can be rewritten into longer imperative variants that avoid extra allocations.

You are right that you can have subtle changes in behavior with similar high level optimizations. For example, most functional languages make calls like these actually create a new collection at each call. If any of these functions can throw and exception or cause an effect, then we cannot perform the above rewriting because if will call the functions out of order. But if a compiler can take the time to analyze functions for external purity, these can be optimized as well.

Re: Random Acts of Optimization

#60

This brings up a thought that I've had for a very long time. Almost every type of optimization that a programmer could employ is repeatable. It involves matching patterns ("Identification" in the context of this article), analysis ("Comprehension"), and rewriting ("Iteration"). All of these steps can be efficiently automated. And it turns out that compiler writers collectively know about the vast majority of these te…

Insulation from performance concerns also makes your performance model less predictable. Because the ends of optimisations are observable, but their means are not, people resort to “butterfly programming”. As a small example, in ActionScript 3, people used to write their conditionals like this: if (a) if (b) { ... } Rather than this: if (a && b) { ... } Because the dumb compiler generated better code for the former.…

> Optimisers are like garbage collectors—they give you better ergonomics than, and equal average performance to the manual alternative, if you’re willing to relinquish predictability and a non-voodoo mental model of your code’s performance.

This is why I'd like to see optimizers become less opaque. It would be great if we could not only suggest optimizations to the compiler (and more sophisticated ones that just inlining), but actually see the process which our code went through.

One language that has some interesting things going on in this area is Nim, which lets you write your own domain-specific optimizations[1].

[1]: http://hookrace.net/blog/what-is-special-about-nim/#add-your...

Post reply on HN