1. 42
  1. 6

    Pretty nice comparison. Since author is on this forum, would it be possible to show the performance of the tree-walking approach over various go versions? That would give a nice overview of different optimizations in all versions.

    1. 7

      I’ve now updated the article with a collapsed section showing a chart of results with the tree-walking interpreter. Chart and table. It follows much the same trajectory, though you can see the jump down at 1.17 due to the register calling change.

      1. 1

        That’s a really good idea. In the next couple of days, I’ll re-run those benchmarks on the tree-walking interpreter across the different Go versions, and post the results here.

      2. 3

        Does 1.18 already contain generics?

        1. [Comment removed by moderator pushcx: Dismissive scorn.]

          1. 15

            I feel this overly dismissive. You seem to be unimpressed by the state of the Go compiler or it’s progress, I presume. I think it’s a matter of focus. Go users have enjoyed superb support for massive concurrency from day 1, way before 1.0. I could make make your argument for many other technologies with regard to concurrency, also with decades as a timescale :)

            The article contains just what it says, which is nice. As a long time Go user it was interesting so see when things changed a lot - I forgot along the way.

            1. 3

              It is true that I have little interest in the go language or its implementation. But regardless:

              1. I am not criticizing the go compiler for making slow code; I am only criticizing the linked post for saying it is good that the go compiler makes slow code.

              2. Languages such as java, erlang, pony, and e are arguably decades ahead of go wrt concurrency. Which is—again—not a criticism of the language, only a criticism of certain claims that people might make about it.

              1. 20

                I am only criticizing the linked post for saying it is good that the go compiler makes slow code.

                Only, you know, it didn’t.

                1. 17

                  Re 1: name a single language that produced the most efficient machine code possible since version 1.0 of the compiler. The article isn’t praising Go for producing slow code, it’s praising the progress that’s been made since the first version.

                  Re 2: of the three languages you name, Java has no language implementation of green threads and Pony is - as of today - a toy language with a tiny community while Go is used in production all over the place.

                  I say this as someone who has used Go in anger and is not a fan: your criticism sounds more like hatred of Go and it’s community than actual valid criticism of the language itself.

                  1. 15

                    Re 1: name a single language that produced the most efficient machine code possible since version 1.0 of the compiler. The article isn’t praising Go for producing slow code, it’s praising the progress that’s been made since the first version.

                    I wouldn’t consider that to be a feature, but both Rust and Pony started from a much better place than Go. Go decided to build on the Plan 9 compiler infrastructure, rather than LLVM (or even GCC), and so left a lot of performance on the table. It also opted for an everything-on-the-stack calling convention, ignoring 20+ years of research defining better calling conventions. That alone gave them a 10%+ slowdown versus just doing what the platform ABI mandated.

                    There’s a lot of stuff in Go, such as the GC and channels implementation, that I’d expect to see improve gradually over time, but there’s also a lot of low-hanging fruit that the Go compiler left on the floor early on because of NIH syndrome. gccgo was a lot faster in straight-line execution but used pthreads for goroutines, which impacted scalability and parallel execution performance and used a different (much worse) GC. This was, in part, because the Go runtime needed to be compiled with the Plan 9 C compiler and so using it from anything else was painful.

                    I think it’s fair to claim that a lot of the speedups in the Go compiler are because they are catching up with the performance of off-the-shelf compiler libraries, rather than because they’re doing anything novel.

                    1. 6

                      @rsc has commented on HN about why they used the Plan9 toolchain.

                      1. 2

                        Re: segmented stack. As someone who wrote parts of Rust’s segmented stack support for LLVM, it was not that difficult. (Yes, pre-1.0 Rust used segmented stack.) I accept it was difficult for Go team, but it would have worked fine for other teams.

                      2. 4

                        Those things aren’t without tradeoffs. Building on LLVM or GCC would very likely make for lengthier compile times and the language probably wouldn’t ever become self-hosting. Moreover, if Pike et al had to learn LLVM or GCC before breaking ground, Go might not have manifest in the first place. Yeah, Go could have started from a more optimal place, but that probably would have made a negligible impact on the language’s overall success.

                        1. 1

                          This is fair criticism. If anything, Go’s NIH and stubborn insistence on doing things ‘their way’ is my least favorite misfeature of the language. As I said, I’ve used Go in anger (I’ve built a business around highly-available systems built on Go) so I’ve experienced its warts personally. The complete mess that is the GOPATH/module migration scenario makes my head hurt every time I think about it.

                          With that said, there’s always people that hate one technology or another and feel the need to make it known every time that technology comes up in conversation (conversely, there’s a bunch of fanbois of every technology). Sounded like the previous commenter was more interested in stating his dislike of everything Go than giving real feedback.

                        2. 4

                          I really do not understand these responses, and will desist from this conversation now. But, one more time, in case it wasn’t clear: I am making no criticism of the go language itself. None whatsoever. Nor criticisms of its community at large. I am only criticizing specific claims made about go.

                        3. 5

                          Genuinely curious and would greatly appreciate your response. Why do you consider Java ahead of Go in regards to concurrency? I’ve never seen anyone claim that before and I haven’t kept up to date with new additions to Java so I’m not sure how true that is.

                          1. 3

                            Yeah, I don’t know what the poster meant, but it doesn’t make a lot of sense. Concurrency in Java today looks pretty much the same as writing concurrent code in the 90s looked like. There’s frameworks and libraries that simplify it - say, Akka - but in most cases they are designed around features provided by other languages running on the JVM (Scala, Kotlin, Clojure, etc). I’d be surprised to find that Java has evolved so much since the last time I used it (around 2017) that it’s now easier to manage massive concurrency in it than it is in Go.

                    2. 1

                      First, countwords, a string processing task that counts the frequencies of words in the input and prints out the words with their counts. This is the kind of thing that’s typical for an AWK script.

                      [OT] And incidentally also for Spark job demos, and awk is likely faster, lol.

                      1. 1

                        Why are the versions inverted? I read the post too and it says:

                        Below is a comparison of GoAWK’s performance when compiled using each released version of Go from 1.2 (the earliest version I could download) to 1.18 (which is in beta now)

                        Am I missing anything?

                        1. 3

                          What do you mean by them being inverted? That’s 1.18 and not 1.1.8, if that’s what you’re missing :)

                          1. 1

                            Thanks for taking time to explain it, I see it now.

                            My sleepy brain kept parsing these as decimals instead of version numbers, so I couldn’t comprehend how 1.2 < 1.18.