Go против Python

Бенчмарки

Как нам сравнивать языки? Обычно начинают с бенчмарков. Ок, давайте тоже так сделаем.

Есть бенчмарк web:

Результаты:

Языкфреймворкrpslatency, ms
Gofasthttp329k0.4±0.2
native http, chi128k2.9±1.7
Pythonuvicorn/starlette, gunicorn65-71k7.1±3.0
aiohttp30k14.9±5.5
django/tornado/flask14-23k2.0±0.8

Источник: techempower.com/benchmarks

Аллокации в Python

json.loads() работает 193 миллисекунды, это долго!

В Go это примерно так же долго, зато там есть кеш в памяти. Давайте так же в Python! Что если если shared cache?

Так, а если не shared?

Вывод: Python не подходит для обработки большого количества объектов.

Асинхронность

Кейс — обработка очереди:

На машине 14 ядер. Вопрос: сколько воркеров надо запустить, чтобы утилизировать CPU? Оказывается, что около 100-200, зависит от базы. Если база отвечает медленнее, CPU недогружен. Если быстрее — CPU перегружается, load average 200, машинка перестаёт отвечать.

Нужны корутины. Если корутины, то во время запроса в базу приложение обрабатывает другие потоки. Если не корутины, то всё залочено.

В Go всё хорошо с асинхронностью:

Asyncio

Поэтому приходится выбирать библиотеки, которые поддерживают asyncio.

Коммуникация между тредами

Go: коммуникация между тредами есть из коробки. Python: нет.

Machine learning

Go:

Кейс: рекомендации. Dataset — MovieLens 1M

ЯзыкScikitSVDSVD++
Pythongithub.com/NicolasHug/Surprise2m 13s2h 54m 00s
Gogithub.com/zhenghaoz/gorse1m 48s0h 02m 47s

Оптимизация

Профилирование

В Go профилирование делается в одну строку:

Результаты профилирования

Можно вот так посмотреть:

go-vs-python-01

Есть flame-graph:

go-vs-python-02

Построчный вывод:

go-vs-python-03

Наконец, оптимизация

Разработчики языка всерьёз занимаются оптимизацией и часто рассказывают о результатах.

Online tooling

pprof очень хорош:

Moar Tooling

Ещё фишечки:

Разработка

Зависимости в Go

Своя библиотека в Go

В Go высокодоступная документация. godoc http — и документация доступна на локальной машине, даже если вы в самолёте. Есть один способ собирать документацию — godoc.

Обработка ошибок

Говорят, в Go нет исключений. Неправда, они есть, просто называются паниками.

Задачка: в скольки местах это может сломаться с исключением?

def fetch_user(id: int) -> 'User':
    response = requests.get('/api/users/{0}'.format(id))
    response.raise_for_status()
    return response.json()

Тут могут быть разные исключения, хорошо бы их все обработать. Go позволяет нам это сделать и даже заставляет.

func fetchUser(id string)
  (*User, error) {
  resp, err := http.Get(`/api/users/`+id)
  if err != nil {
    return nil, errors.Wrap(err, `get user by id`)
    }

  // теперь обработаем код ответа
  if resp.StatusCode != http.StatusOK {
    return nil, errors.Wrap(errors.New("API got status " + resp.Status), `get user by id`
  }
  user := &User{}

  // теперь декодируем
  if err = json.NewDecoder(resp.Body).Decode(user); err != nil {
    return nil, errors.Wrap("Incorrect user profile", err)
  }
  return user, nil
}

Кодировки

Выводы

Опытному бэкендеру на самом деле не важно, на чём писать.

Зарплаты

ЯзыкМойКруг, РФGetIT, Москва, seniorStackOverflow, (медиана)
75% (процентиль)90% (процентиль)
Python150 000₽185 000 ₽175-200 000 ₽$98 000 в год
Go178 000₽225 000 ₽201-250 000 ₽$110 000 в год

Вывод: писать на Go выгоднее на 20%!

Когда Python лучше

Когда Go лучше