I am always been fascinated about speed, from overclocking hardware to efficient algorithms, but I always struggle with compiled programming languages and concurrency, I remember my early days as a developer shooting my foot with this concepts. For compiled programming languages I used to say: “well this binary is fast enough I don’t need more speed”; or for scripting languages: “Hey! it only runs once, I dont need to speed things up”. But then I got involved on web applications development I found that speed matters. If you have a latency greater than a second, your users will start to complain, so is better to be fast.
Nobody complains if you make your code faster
While I was building this site I wanted to have a pretty styled badges from my github account, but I could not found any service that I liked. So I decide to build my own badge system to pull from my github repositories statistics to present them nicely. The problem was simple fetch your repositories, get the programming languages on each one of them and add it into a single hash. Very simple, right?
The first solution isn't always best
On my first approach I build it through javascript using async ajax calls, but I found that there is a limit on request on the api, to avoid that you need to use an oauth token to extend your hourly quota, and also the loading wasn’t good enough, the badges were popping after the page was loaded, so I decide to move forward building a small service with a javascript plugin.
When in doubt benchmark
Although the ruby algorithm was extremely simple, it took me around 15 seconds to fetch all my repositories languages in less than 20 lines of code, it looks a good example to benchmark against go.
Coming from an object oriented paradigm where everything is an object, it took me a while to consume the RESTful API because contrary to javascript, when you pull a json data on Go you need to specify what do you want to use instead expect that the language parse into an object by itself. Another problem that I found and not very unpleasant was that I needed to write more code, but once I got solved the problem the performance improvement was 4x faster than ruby. I did a great job but I still wasn’t happy 4[s] is not fast enough for a web service and the solution still was 2x slower than the javascript async version.
I figured out that the latency was caused by the secuence on api calls, if I had 20 repositories and each request took me around 185[ms] well there is my bottleneck. So I decided solve this using concurrency for that I had to implement another get method using channels, instead returning a value and fetch each repository language using go rutines, the result was fantastic, the whole process took less than a second. I MADE IT!!
Concurrency in Go is painless, but you will have to be more declarative and write more code.
If you want to check the project just visit here or keep on eye on the code