Live data from Hacker News

Mid-stack inlining in the Go compiler

docs.google.com

41–50 of 76 posts

Re: Mid-stack inlining in the Go compiler

#41
post #9

Earlier quoted context omitted.

The presentation makes a distinction between mid-stack and leaf inlining, and apparently it was only done on leaf calls before because this is less confusing in backtraces.

The point is, as usual, Go is trying to catch up to what everyone else has had for years. The use of non-standard terminology here is suspicious, raising the question that the Go people are trying to hide the fact that they are playing catch-up.

I don't think anyone is pretending that Go is a decades-old language. What is the standard term for this kind of inlining which would distinguish it from the inlining already present in the compiler?

Re: Mid-stack inlining in the Go compiler

#42
post #9

Earlier quoted context omitted.

The presentation makes a distinction between mid-stack and leaf inlining, and apparently it was only done on leaf calls before because this is less confusing in backtraces.

The point is, as usual, Go is trying to catch up to what everyone else has had for years. The use of non-standard terminology here is suspicious, raising the question that the Go people are trying to hide the fact that they are playing catch-up.

No hiding or sneaking is necessary to explain anything here. They needed to come up with a way to describe the difference between how it is currently implemented and how they are changing it. That's all.

Re: Mid-stack inlining in the Go compiler

#43
post #41

Earlier quoted context omitted.

The point is, as usual, Go is trying to catch up to what everyone else has had for years. The use of non-standard terminology here is suspicious, raising the question that the Go people are trying to hide the fact that they are playing catch-up.

I don't think anyone is pretending that Go is a decades-old language. What is the standard term for this kind of inlining which would distinguish it from the inlining already present in the compiler?

The point is "inlining" already refers to this kind of inlining. The already-present form is more limited than the typical use of the term.

Re: Mid-stack inlining in the Go compiler

#44
post #40
post #26

Earlier quoted context omitted.

The compiler got a bit slower: https://github.com/golang/go/issues/19386 Those numbers are just for my CLs that fix stack traces but with mid-stack inlining still off. Turning it on makes builds noticeably slower: $ time ./make.bash real: 45.32s user: 118.67s cpu: 5.85s $ time GO_GCFLAGS='-l=4' ./make.bash real: 64.51s user: 167.04s cpu: 7.12s We'll need to tweak the inlining heuristic to find a good balance between…

Please have a switch where I can sacrifice build time for maximum possible runtime benefits.

The compile-time/run-time tradeoff is interesting. Getting the "maximum possible runtime benefits" probably calls for https://en.wikipedia.org/wiki/Superoptimization :)

Re: Mid-stack inlining in the Go compiler

#45
post #8

It doesnt look like this solves inlining library calls?

Go already performs cross-package inlining, so it can already inline library calls. (This is relatively easy to do in Go compared to other languages because packages must form a DAG. Compiling package A writes out enough information in the object file for A that compiling package B that depends on A can inline calls to functions in A.)

> This is relatively easy to do in Go compared to other languages because packages must form a DAG.

That doesn't make sense to me. The complicated part is storing the IR in packages in a form that can be read back into the compiler later. That's needed to do inlining at all. Once you have that done, doing LTO is trivial: you just slurp your IR for all modules linked together into the compiler and emit a single binary. (You can be fancier, like ThinLTO does, but again, the effort needed to do ThinLTO is independent of whether you have cyclic dependencies or not.)

Re: Mid-stack inlining in the Go compiler

#46

Earlier quoted context omitted.

"Compiling package A writes out enough information in the object file for A that compiling package B that depends on A can inline calls to functions in A" So it records the calling convention, architecture flags, alignment, and other ABI pieces etc? As well as an estimate of instruction-level inlining cost, summary info about arguments, etc, so you effectively decide whether inlining it will help or hurt, without hav…

"So it records the calling convention, architecture flags, alignment, and other ABI pieces etc?" No. At the moment it records the AST in the object file, because the inliner works at the Go AST level. In the future it may instead record the SSA representation (which would obviously give better cost estimates; the current heuristics are really extremely simple). "FWIW: Writing out the info is usually not the hard part…

"In the future it may instead record the SSA representation (which would obviously give better cost estimates; the current heuristics are really extremely simple)."

This would be identical to what others do then :)

"The DAG-ness means it's always available when compiling the call site, even if it's a cross-package call. It means you don't have to do it at link time. "

This is unrelated to DAG-ness. Unless you mean something else by DAG-ness. DAG-ness means it's a directed-acyclic graph. That is, all other things being equal, it has no cycles.

This is unrelated to the problem.

For example, in other languages/etc, it could be weakly defined, or other some form of overridable, regardless of whether it has cycles, is actually multiply defined etc. That requires link-time resolution, becuase you can't optimize it making an assumption about its callees/callers, or even inline it, and then just hand that version to others because you may have screwed it up in a way one of those other callers depend on.

That is, the overridability is an attribute of the function, not a problem of how it is used.

Ditto on the ABI, alignment, etc.

None of the interesting problems they have to solve are related to packaging. They occur with DAGs or non-DAGs, are just related to these languages supporting a richer set of things you can do to functions :)

Re: Mid-stack inlining in the Go compiler

#47

Earlier quoted context omitted.

"Compiling package A writes out enough information in the object file for A that compiling package B that depends on A can inline calls to functions in A" So it records the calling convention, architecture flags, alignment, and other ABI pieces etc? As well as an estimate of instruction-level inlining cost, summary info about arguments, etc, so you effectively decide whether inlining it will help or hurt, without hav…

"So it records the calling convention, architecture flags, alignment, and other ABI pieces etc?" No. At the moment it records the AST in the object file, because the inliner works at the Go AST level. In the future it may instead record the SSA representation (which would obviously give better cost estimates; the current heuristics are really extremely simple). "FWIW: Writing out the info is usually not the hard part…

> The DAG-ness means it's always available when compiling the call site, even if it's a cross-package call. It means you don't have to do it at link time.

Why is it any harder to do at link time?

(I've implemented this in a production compiler, and choosing whether to do it at compile time or link time was a trivial decision.)

Re: Mid-stack inlining in the Go compiler

#48
post #41

Earlier quoted context omitted.

The point is, as usual, Go is trying to catch up to what everyone else has had for years. The use of non-standard terminology here is suspicious, raising the question that the Go people are trying to hide the fact that they are playing catch-up.

I don't think anyone is pretending that Go is a decades-old language. What is the standard term for this kind of inlining which would distinguish it from the inlining already present in the compiler?

> What is the standard term for this kind of inlining which would distinguish it from the inlining already present in the compiler?

There isn't a standard term, because virtually all inliners always did what Go is now doing. It's pretty basic functionality.

Re: Mid-stack inlining in the Go compiler

#49
post #18

This is absolutely fantastic work. Since I've learned about continuation passing style (which Go channels could probably be formally transformed into), I've been convinced that there's a better way to do codegen. Better calling convention, better stack representation, better instruction architecture; I'm not yet sure - it's a nag continuously at the back of my mind, almost as though it's at the tip of my tongue. In t…

Something like this, in Rust?

https://aturon.github.io/blog/2016/08/11/futures/

Re: Mid-stack inlining in the Go compiler

#50
post #9

Earlier quoted context omitted.

The presentation makes a distinction between mid-stack and leaf inlining, and apparently it was only done on leaf calls before because this is less confusing in backtraces.

The point is, as usual, Go is trying to catch up to what everyone else has had for years. The use of non-standard terminology here is suspicious, raising the question that the Go people are trying to hide the fact that they are playing catch-up.

Comments like these are so depressing. Someone does a bunch of work to improve the Go compiler and writes a presentation to share their approach (primarily so that other people working on Go can understand and extend it), and gives it all away for free. This is textbook open source citizenry, which should be applauded.

But instead, you come along and criticize them for being too specific with their terms (!!) and also accuse them of being deceptive. This is not a marketing exercise. There is no conspiracy here.

Post reply on HN