
Why is this Go faster than the equivalent Java? - boyter
http://www.boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/
======
dietrichepp
The moment I saw the problem I started coding :-)

[https://gist.github.com/depp/3a6f0377284fbb9b33984063856051b...](https://gist.github.com/depp/3a6f0377284fbb9b33984063856051b1)

Rather than brute forcing all possible permutations, we start from all
possible final states and BFS backwards towards starting states. There are
probably tons of opportunities for further optimization, but this takes ~800
ms on my desktop, and it only uses one core. We don't need to track the number
of turns required to end each state, since the frontier will always consist of
games which require the same number of turns to end.

Edit: Shrinking my data structures dropped runtime by 50%, and easy & cheap
parallelism dropped runtime by another 75% on my four-core desktop. New
runtime: 110ms (Intel i5 6600k). The key to the parallelism is that since the
total amount of money never changes, we can assign a different total amount of
money to each thread, and they'll never have to search the same states.

~~~
tboerstad
Wow, this is beautiful C++ code! High level abstractions, not hiding any of
the nitty gritty details, parallelism and all, yet very readable. Well done!

~~~
swah
I felt the same - not that worse than in a modern language (of course someone
should rewrite in Go with the new algorithm so we can decide if it would be
good enough :)

------
otterley
Epilogue:

> EDIT - Thanks to Dolda2000 I have modified the Java version. It is now about
> the same speed as the GoLang version. Indeed the issue was the the games
> were created causing the Java version to have to simulate more games to
> determine if the game went long enough. With the changes it is running in
> about ~6 seconds now and has restored my faith in Java.

[http://stackoverflow.com/questions/43082115/why-is-this-
gola...](http://stackoverflow.com/questions/43082115/why-is-this-golang-
solution-faster-then-the-equivalent-java-solution)

~~~
developer2
This is great, this comment deserves to be at the top. Let's not criticize the
original article, and instead celebrate that its publication resulted in a
crowdsourced solution. I love to see the community coming together to provide
knowledge to us all. :)

------
sofaofthedamned
I love this sort of post, and it makes me miss programming (i'm a Linux
sysadmin type now)

The golden age of this stuff was when I was writing stuff for the Atari ST and
Amiga. Fixed hardware, manuals that came with assembly instructions and
timings, etc.

My greatest moment was when rewriting the Atari ST text output function. For
those that don't remember, the ST had an interleaved bitmap [1] and no
hardware blitter support, so everything was done with the CPU. Therefore
writing text on the screen was hard. I wrote a program that speeded up the C
code from the OS about 3x, then Darek Mihocka with Quick ST [2] beat my
speedup. I was absolutely aggrieved about this, but spent weeks working out
how he did it without any luck.

In the end the solution came to me genuinely when I was dreaming - the
Motorola 68000 move.p instruction which worked quite well with the interlaced
bitmap. It gave me a nearly 2x speedup and the rest of the optimisations I had
meant I beat his code.

I do miss those days of a level playing field where the outcome was the result
of your skills, rather than quibbling over the middleware, OS, graphics driver
version used, etc etc.

[1]
[http://codetapper.com/amiga/maptapper/documentation/gfx/gfx-...](http://codetapper.com/amiga/maptapper/documentation/gfx/gfx-
mode/)

[2] [http://www.atariuptodate.de/en/3907/quick-
st](http://www.atariuptodate.de/en/3907/quick-st)

~~~
chrisper
How is that working out for you? Isn't the pay significantly less being a
sysadmin?

~~~
sillysaurus3
It's illusory to think that we have a choice. It's hard to avoid becoming
obsolete over a long timespan.

~~~
chrisper
I am a bit confused about what you are referring to. Are you saying that we do
not have many choices when it comes to work? I am about to graduate, but a lot
of people seem to be saying that once you gain experience it is easy to hop to
different jobs.

~~~
stonemetal
After a while you get pigeonholed. You can hop jobs easily but it is the same
shit, different name on the building. It is often easier to pivot inside a
company then jump to a new company.

~~~
sverhagen
Personally I would appreciate when those who got pigeonholed into finding
their consecutive jobs "the same sh*t" don't foreshadow that onto those yet to
graduate. It's good that those coming into the job market newly know what to
look out for, but the opportunities mentioned by the previous poster also mean
that you can steer away from such shotty (I'm going with the auto-complete
here) jobs... if you choose so.

~~~
indemnity
Agreed. I've been a sysadmin, tech support nerd, developer, architect and now
product manager. With each switch the value you bring jumps.

Next switch is likely starting a business.

37 y.o., still not tired of this!

I can see how someone could get bitter if they stayed in the same
role/position most of their career, but in my experience this has tended to be
people with a negative outlook/attitude/chip on shoulder in general... It
really is what you make of it, people are people wherever you go, some are
dicks, some are not.

Just accept the reality of the game and deal with it.

You don't need to spread your aura of doom everywhere you go.

------
quanticle
tl;dr: The Go implementation being faster has nothing to do with Java or Go.
The version implemented in Go used a slightly different algorithm, which
allowed hot inner loops to terminate early, greatly improving the performance
of the algorithm.

~~~
weberc2
I like Go, but it's not dramatically faster than Java. Any contest between the
two of them will probably just be a back and forth of optimizations. They
share pretty much the same upper bound.

~~~
tomohawk
Given a specific machine with a set amount of cpu, ram, and io bandwidth, I
find I can easily do more on that machine with go than java.

Also, try running multiple java processes on a machine as opposed to multiple
go programs.

~~~
weberc2
So could I. I imagine a Java aficionado would say the opposite. Like I said,
different ways to think about the problem.

~~~
donatj
To the posters point about running multiple Java aaps on a single machine, I
think ram is the real issue. Java makes in my experience far less frugal use
of it. I've seen Java applications eat hundreds of mbs of ram rewritten in Go
using 1-2 mb.

~~~
weberc2
Every time I hear this conversation play out, the Java folks point out that
the GC is highly tunable/pluggable, so you can shift some levers and get lower
memory consumption in exchange for more frequent collections. I'm not a GC
expert, so I'm just repeating what I've heard.

~~~
mcguire
This is true. The Java GC (and the whole VM) is one of thr most impressive
pieces of software in existence. There are several GCs available, they're
tunable, and they support monitoring better than any other I've seen.

No GC I know is happy without a heap several times larger than the program's
requirements.

OTOH, Java programs tend to be built using frameworks that soak up memory like
crazy. So there's that.

~~~
FlyingPiranhas
I believe that Go's GC currently bounds heap memory usage to 2x the actual
usage (worst case).

------
bitcharmer
I'm surprised the warmup problem in Java hasn't been invoked here yet. Java
has bootstrap and warm-up overhead which for comparisons like this one may
have a decisive impact on the perceived results.

What will happen is (after the JVM starts), there will be (by default) 10000
interpreted iterations, then shortly after that a stop-the-world pause to
replace slow interpreted code with its native counterpart JITed by a compiler
thread, and probably a few more of those either optimising other, less hot
parts of the code, or applying more aggressive optimizations on already JITed
sections.

Go comes with AOT compilation and as far as I know, doesn't have much initial
overhead. For a test that takes few seconds to complete, I'd say this is not
how you want to compare performance.

~~~
jnordwick
There is no stop the world point. There are compilation threads always running
in the background patching hot code.

In Java 8 tiered compilation became the default. After a first threshold is
reached, a method or loop will be compiled as a first approximation with
further record keeping. At the second threshold, a more aggressively optimized
version without record keeping will be put in place. This is kind of like the
merging of the old C1 and C2 compilers into one to help get up to speed
quicker.

When you want to measure this stuff you use JMH, Java Microbenchmarking
Harness, an amazing piece of work that will warmup the JVM before executing
performance tests. Be very careful writing your own Java timing code, and for
the most part rely on JMH.

------
jaimex2
I seem to be missing the point or lesson of the post?

Speed comparison between two languages, botched the Java algorithm... and ...?

~~~
hehheh
And the final result was that the two languages had roughly the same
performance, which may surprise folks that believe Java is still a slow
language.

~~~
bluejekyll
It hasn't been slow since basically 1.3 when HotSpot became default.

~~~
pjmlp
Urban legends tend to live forever.

~~~
aisofteng
I think that there is probably a large overlap between the population of
people who believe this and the population of people that don't really know
what bytecode or JIT compilation are.

In fact, I have asked a number of people under the impression that Java is
slow to explain why they think it is slow. The answers have two flavors:

1\. Its high level abstractions are computationally expensive. Sometimes this
idea is supported by saying that garbage collection is very slow, sometimes by
saying that the inability to directly manage memory means that it is done
inefficiently, perhaps even inescapably so.

2\. Compiling a program to an intermediary language that is not assembly but
must be instead executed by something else (in this case, the JVM) must be
slow.

~~~
wuch
Controlling memory layout is one area that is very important for performance,
where Java does not exactly shines. You essentially have to store your data in
arrays of primitive types, to avoid memory overhead of objects (pointer to
class, lock, gc bits) and additional indirection during access. While not
exactly impossible, Java makes it quite inconvenient and costly to write code
that takes control of memory layout.

~~~
pjmlp
Hence why there are ongoing improvements targeted to Java 10, to change
exactly that.

Until then there are the IBM and Azul extensions, off heap memory, or
optimizing in native code that 1% after using the profiler, where it really
matters.

------
Ari_Rahikkala
Just for the sake of having another solution for the same problem, here's the
basically-zero-thought-required brute-force search solution in C:
[https://gist.github.com/arirahikkala/ef1a07dbd5a8ca3a077c03c...](https://gist.github.com/arirahikkala/ef1a07dbd5a8ca3a077c03c3f4efcfde)

Not as fast as dietrichepp's solution, but not terrible either, and probably
the winner in terms of memory use. Since there's no state to keep track of,
adding parallelism with OpenMP was trivial, too.

------
Too
Wouldn't it be possible to reduce the number of input combinations to all
combinations where the proportion of money for each player is the same? For
example (1,4,6) should give the same result as (2,8,12), but with different
scaling-factor.

Find all random games for those proportions which end after 12 turns, then
change the scaling factor to make it less than 255?

------
nhumrich
The article says he doesn't buy that Java is slow. But the JVM is a JIT with a
pretty significant warm-up time. Its designed for long running processes, and
if you only doing things that are running for a couple seconds, then yes, Java
is slow. Java becomes fast only after it's been running for a while.

~~~
hyperpape
The article is a counterexample to your claim. The Go program and the Java
program ran in effectively the same amount of time.

I made this point in more detail upthread, but: for some CLI tasks that need
to run in a few seconds, JVM performance will be adequate. For others, it will
suffer.

------
echelon
I get the sense that the author doesn't know about algorithmic complexity.
This has nothing to do with language choice and everything to do with the
algorithms used.

~~~
aisofteng
I, on the other hand, get the feeling from reading the article that the author
understands that this performance difference was due to implementation
differences, but wanted a more attention-grabbing title.

My subjective impression is that this is the first time the author has come
across this sort of consideration in implementation and wanted to write about
it. There is nothing wrong with that - in fact, I think it's great! It's just
that the title leads one to expect, well, quite a bit more.

~~~
boyter
Not the first time but the first time in a while and the first time I have
ever written about the process. I was literally just writing down my
experience post event.

The title was just taken from the Stackoverflow post which I agree in this
context is a little click baity.

I never expected it to get this much attention though, as stated in the first
sentence it was just something I did for myself more than anything.

------
delinka
The HN title doesn't match TFA title. HN has a grammatical error.

~~~
dang
Yes! Fixed. Sorry, we usually don't miss those for that long.

------
haddr
The title is misleading in a way making it a click bait. The article is cool,
though. Both languages are equally fast.

------
segmondy
That problem is that type of problem that is well suited for a prolog system
with a constraint library.

~~~
todd8
Some of these types of problems can indeed be turned over to a constraint
solver. I'd love to see a comparison with Prolog. Has anybody tried it?

The problem that I see with Prolog in this case is that a simple solution is
simple because it is turning the search over to Prolog's built in constraint
solver that knows nothing of the problem. This often leads to unacceptable
performance with Prolog; performance problems can sometimes be addressed in
practice by the appropriate placement of the cut operator within the logical
specification of the constraints. This, at least in my experience, makes
understanding what the program is doing very difficult.

Generally, I view Prolog (along with languages like Smalltalk) as a language
appropriate for some problem domains that have come to the _end of their
lifetime_ because mainline, more generally useful, languages have adopted
their features or incorporated them in libraries.

------
intrasight
faster then?

------
stcredzero
Than

------
bigdubs
Capitalization of `GoLang` should actually be `golang`.

It's also not automatic that golang is strictly faster than well tuned java
vms.

