165

Why We Switched From Python to Go, Part 1 - DZone Performance

 6 years ago
source link: https://dzone.com/articles/why-we-switched-from-python-to-go
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Switching to a new language is always a big step, especially when only one of your team members has prior experience with that language. Early this year, we switched Stream's primary programming language from Python to Go. This post will explain some of the reasons why we decided to leave Python behind and make the switch to Go.

Reasons to Use Go

Reason 1 - Performance

Go is extremely fast. The performance is similar to that of Java or C++. For our use case, Go is typically 30 times faster than Python. Here's a small benchmark game comparing Go vs Java.

Reason 2 - Language Performance Matters

For many applications, the programming language is simply the glue between the app and the database. The performance of the language itself usually doesn't matter much.

Stream, however, is an API provider powering the feed infrastructure for 500 companies and more than 200 million end users. We've been optimizing Cassandra, PostgreSQL, Redis, etc. for years, but eventually, you reach the limits of the language you're using.

Python is a great language but its performance is pretty sluggish for use cases such as serialization/deserialization, ranking, and aggregation. We frequently ran into performance issues where Cassandra would take 1ms to retrieve the data and Python would spend the next 10ms turning it into objects.

Reason 3 - Developer Productivity and Not Getting Too Creative

Have a look at this little snippet of Go code from the How I Start Go tutorial (this is a great tutorial and a good starting point to pick up a bit of Go).

package main

type openWeatherMap struct{}

func (w openWeatherMap) temperature(city string) (float64, error) {
resp, err := http.Get("http://api.openweathermap.org/data/2.5/weather?APPID=YOUR_API_KEY&q=" + city)
if err != nil {
return 0, err
}

defer resp.Body.Close()

var d struct {
Main struct {
Kelvin float64 `json:"temp"`
} `json:"main"`
}

if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
return 0, err
}

log.Printf("openWeatherMap: %s: %.2f", city, d.Main.Kelvin)
return d.Main.Kelvin, nil
}

If you're new to Go, there's not much that will surprise you when reading that little code snippet. It showcases multiple assignments, data structures, pointers, formatting, and a built-in HTTP library.

When I first started programming I always loved using Python's more advanced features. Python allows you to get pretty creative with the code you're writing. For instance, you can:

  • Use MetaClasses to self-register classes upon code initialization.
  • Swap out True and False.
  • Add functions to the list of built-in functions.
  • Overload operators via magic methods.
  • Use functions as properties via the @property decorator.

These features are fun to play around with but, as most programmers will agree, they often make the code harder to understand when reading someone else's work.

Go forces you to stick to the basics. This makes it very easy to read anyone's code and immediately understand what's going on.

Note: How "easy" it is really depends on your use case, of course. If you want to create a basic CRUD API I'd still recommend Django + DRF, or Rails.

Reason 4 - Concurrency and Channels

As a language, Go tries to keep things simple. It doesn't introduce many new concepts. The focus is on creating a simple language that is incredibly fast and easy to work with. The only area where it does get innovative is goroutines and channels (to be 100% correct the concept of CSP started in 1977, so this innovation is more of a new approach to an old idea.) Goroutines are Go's lightweight approach to threading, and channels are the preferred way to communicate between goroutines.

Goroutines are very cheap to create and only take a few KBs of additional memory. Because Goroutines are so light, it is possible to have hundreds or even thousands of them running at the same time.

https://tour.golang.org/concurrency/1

You can communicate between goroutines using channels. The Go runtime handles all the complexity. The goroutines and channel-based approach to concurrency makes it very easy to use all available CPU cores and handle concurrent IO - all without complicating development. Compared to Python/Java, running a function on a goroutine requires minimal boilerplate code. You simply prepend the function call with the keyword "go":

package main

import (
"fmt"
"time"
)

func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}

}

func main() {
go say("world")
say("hello")
}

Go's approach to concurrency is very easy to work with. It's an interesting approach compared to Node where the developer has to pay close attention to how asynchronous code is handled.

Another great aspect of concurrency in Go is the race detector. This makes it easy to figure out if there are any race conditions within your asynchronous code.

Reason 5 - Fast Compile Time

Our largest microservice written in Go currently takes 6 seconds to compile. Go's fast compile times are a major productivity win compared to languages like Java and C++ which are famous for sluggish compilation speed. I like sword fighting, but it's even nicer to get things done while I still remember what the code is supposed to do.

Image title

Reason 6 - The Ability to Build a Team

First of all, let's start with the obvious: there are not as many Go developers compared to older languages like C++ and Java. According to StackOverflow, 38% of developers know Java, 19.3% know C++, and only 4.6% know Go. GitHub data shows a similar trend: Go is more widely used than languages such as Erlang, Scala, and Elixir, but less popular than Java and C++.

Fortunately, Go is a very simple and easy to learn language. It provides the basic features you need and nothing else. The new concepts it introduces are the " defer " statement and built-in management of concurrency with "go routines" and channels (for the purists: Go isn't the first language to implement these concepts, just the first to make them popular). Any Python, Elixir, C++, Scala, or Java dev that joins a team can be effective at Go within a month because of its simplicity.

We've found it easier to build a team of Go developers compared to many other languages. If you're hiring people in competitive ecosystems like Boulder and Amsterdam this is an important benefit.

Reason 7 - Strong Ecosystem

For a team of our size (~20 people) the ecosystem matters. You simply can't create value for your customers if you have to reinvent every little piece of functionality. Go has great support for the tools we use. Solid libraries were already available for Redis, RabbitMQ, PostgreSQL, Template parsing, Task scheduling, Expression parsing, and RocksDB.

Go's ecosystem is a major win compared to other newer languages like Rust or Elixir. It's of course not as good as languages like Java, Python or Node, but it's solid and for many basic needs you'll find high-quality packages already available.

Reason 8 - Gofmt, Enforced Code Formatting

Let's start with, what is Gofmt? And no, it's not a swear word. Gofmt is an awesome command line utility, built into the Go compiler for formatting your code. In terms of functionality, it's very similar to Python's autopep8. While the show Silicon Valley portrays otherwise, most of us don't really like to argue about tabs vs spaces. It's important that formatting is consistent, but the actual formatting standard doesn't really matter all that much. Gofmt avoids all of this discussion by having one official way to format your code.

Reason 9 - gRPC and Protocol Buffers

Go has first-class support for protocol buffers and gRPC. These two tools work very well together for building microservices which need to communicate via RPC. You only need to write a manifest where you define the RPC calls that can be made and what arguments they take. Both server and client code are then automatically generated from this manifest. This resulting code is both fast, has a very small network footprint, and is easy to use.

From the same manifest, you can generate client code for many different languages even, such as C++, Java, Python, and Ruby. So, no more ambiguous REST endpoints for internal traffic, that you have to write almost the same client and server code for every time.

Come back tomorrow when we'll explain the disadvantages of Go, and how it compares head-to-head with Python! 


Recommend

  • 179

    Why and how I switched to KotlinI’m one of the very few (judging from my twitter stream) who weren’t jumping up and down out of excitement when Google announced Kotlin as a first tier language in Androi...

  • 3
    • fuzzyblog.io 3 years ago
    • Cache

    Why I Haven't Switched Away from OSX

    Why I Haven't Switched Away from OSX Jul 19, 2017 I'm writing this at 4:12 am sitting next to a machine with 11:50 hours of uptime. The machine I'm using is an old OSX Macbook Air running OSX El Capitan 10.11.6 and the...

  • 11

    Why broot switched to Hjson for its configuration files 14 minute read Published: 2020-12-22 TOML was originally the only format for configuring broot. Here I explain why Hjson is now...

  • 2
    • blogs.sap.com 3 years ago
    • Cache

    Why I switched to Neovim

    Technical Articles

  • 4

    Why I switched from Aussie Broadband NBN to Future Broadband Performance NBNWe moved house a few weeks ago and I chose Future Broadband Performance NBN because it has a unique service offering...

  • 3

    Introduction Honestly, my motivation for looking into Docker was to see what all the hype was about… is the hype true? Can Docker really help out with my development experience? Can Docker make deploying a web application easier?...

  • 1

    WP Engine Review: Premium Managed WordPress Hosting BySteven Snell UpdatedApril 22, 2021Hosting This page may include links to our sp...

  • 2
    • lisp-journey.gitlab.io 2 years ago
    • Cache

    Why Turtl Switched From CL to Js

    Why Turtl Switched From CL to Js Turtl is a very well done, secure collaborative notebook web app. https://turtlapp.com Its api backend is built in Common Lisp:

  • 1

    Why we at $FAMOUS_COMPANY Switched to $HYPED_TECHNOLOGY Sunday, May 10, 2020 When $FAMOUS_COMPANY launched in 2010, it ran on a single server in $TECHBRO_FOUNDER’s garage. Since then, we’ve experienced...

  • 4
    • patkoscsaba.blogspot.com 2 years ago
    • Cache

    Why I Switched Back to Samsung from OnePlus Phone?

    Why I Switched Back to Samsung from OnePlus Phone?  Every person has their own preferences and needs. Every one of use are using our phones in a slightly different manner. I think there is no perfect phone. Each one will some sma...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK