I finally found some time to look at the Go programming language (aka
golang). In order to get a feeling for it I picked a random Google code jam problem and programmed it in Go.
The code used in the experiments that follow is pretty simple
My first impressions were mostly positive:
- decent documentation covering the language proper as well as the standard library
- a fast compiler resulting in short edit-compile-test cycles
- a nice standard library and a wealth of packages (provided by the community)
- a lively and friendly mailing list and
The language has quite a “direct” feel to it: I could get to work and be productive almost immediately.
This is in stark contrast to other languages I tried to learn recently e.g. Scala (back in January): it required a lot of reading and even a couple of days into it I was not really productive in Scala.
Go is quite the opposite, the barrier to entry is low, the language is clean and simple. The combined declaration and initialisation operator (
':=') alone is a godsend.
Coming from a Python background the main thing I was missing was the REPL. Who knows, maybe there is even one out there but I just did not find it yet..?
playing with goroutines
One of the most attractive
golang features is its support for concurrent programming via goroutines and I wanted to play with these.
The programming problem chosen came with an input for 50 calculations. I used it to create inputs with 50, 100 and 200 *thousand* calculations. All calculations are independent of each other i.e. ideally parallelisable.
Being a fairly young language still
Go does not parallelise code by default. If CPU parallelism is desired one must tell the run-time how many goroutines shall execute simultaneously.
The code I wrote starts each calculation in a separate goroutine and allows the user to specify the number of CPUs/cores that should be used to execute the program.
Using a bash script I ran the resulting program varying both the number of calculations and the number of CPU cores.
These experiments were conducted on a 32-core server (Quad-Core AMD Opteron Processor 8356) with 64GB of RAM running
Ubuntu 11.04 server. Also, I ran each configuration for three consecutive times and used the average duration in the graph below.
golang run-time was not able to utilise more than 8 cores when running this particular program.
As can be seen from the graph (full size) above, executing the program on more than 8 cores did not decrease its running time futher.
200K calculations input file is a bit over half a gigabyte so I suspected that the program is dominated by I/O and the goroutines cannote execute because the result channel is full.
That lead me to experiment with different result channel sizes. The resulting running times (e.g. for
200K calculations) can be seen in the graph (full size) below.
However, varying the result channel sizes did not seem to have a big effect.
Anyway, I am pretty happy with the code at this point but suggestions are always welcome, particularly those aiming at improving the degree of parallelism :-)
I am amazed how far I got by investing approx. 10 hours in learning
Go and programming in it.
python almost exclusively for the last 5 years I am pretty spoiled when it comes to code conciseness and productivity.
Go is not too far away though, and, programming in it was fun and enjoyable.
I will definitely continue to explore it. Maybe you should give it a whirl as well :-)