вторник, 27 ноября 2012 г.

Golang and supervisor

  Попробовал использовать Supervisor (http://supervisord.org) для обеспечения отказоустойчивости Go фронтэнда. Оказался очень даже доволен результатом. Простая настройка и установк, куча опций. Плюс к тому он еще и логи фронтенда собирать может. Короче думаю с этим можно жить. Единственная сложность возникла на этапе установки нужных разрешений: в случае если супервизору чего-то нехватает - он просто умирает, а так как он уже отключился от консоли - ты собственно ничего не видишь. Для того чтобы отладить все эти проблемы нужно запустить его первый раз с ключом -n 

пятница, 23 ноября 2012 г.

Go(golang) vs PHP по взрослому

      Я давно хотел устроить сравнение скорости Go и PHP на какой-нибудь реальной задаче  и в условиях близких к боевым. Интернеты кишат синтетическими тестами - например  вычисление квадратных корней в милион потоков  - причем эти тесты чаще всего выполняются на ноутбуке. 
    Итак, есть реальная задача - backend для автосаджеста городов. На вход передается набранная строка - возвращается список возможных городов в JSON. Сами города находятся в sphinx, в количестве 30 тысяч. 
Что с чем сравниваем:
    Текущая реализация написана на PHP c использованием фреймворка Yii. Состоит буквально из 10 строчек, 5 из которых комментарии. Естественно используется opcode cacher.  
   Go реализация занимает чуть побольше - 35 строчек кода. Тестировалось 2 варианта FastCGI и HTTP. Различаются они фактически только подключаемой библиотекой - "net/http" или "net/http/fcgi".  Забегая вперед сразу скажу - разница между этими реализациями лежит в пределах погрешности - менее 1 сотой секунды.
    На чем собственно проводилось тестирование: PHP реализация была разложена на 2-х фронтах(Intel Xeon 8CPU/32GB RAM/Ubuntu 12.xx).  Go реализация была разложена только на одном фронте - потому как деплойный скрипт написан именно под PHP, а раскидывать ручками больше чем на один сервер было лень.
       Как тестировалось: был сгенерирован список URL для siege, состоящий примерно из 250 тысяч различных запросов к автосаджестеру. siege запускался с одного из фронтов - чтобы не учитывать сетевые задержки. Тестировалось с 30, 40 и 50 одновременных соединений.
        Итак результаты:
При 30 одновременных соединениях
Среднее время ответа: PHP - 0.36 секунд, Go - 0.01 секунда.
Самая длинная транзакция: PHP 12.04 секунды, Go - 5.02 секунд.
Самая короткая транзакция: PHP 0.02 секунды, Go - 0.00 секунд.

При 40 одновременных соединениях
Среднее время ответа: PHP - 0.65 секунд, Go - 0.09 секунд.

При 50 одновременных соединениях
Среднее время ответа: PHP - 0.96 секунд, Go - 0.22 секунд.

Выводы:
1. Переписывание на Go данной задачи выглядит более чем оправдано.  
2. При увеличении числа одновременных подключений разница между GO и PHP сильно сокращается. Объяснение этому одно - начинает засасывать sphinx - который запущен только на одном сервере. Также на это повлияло то что siege был запущен на одном из фронтов. 

Также я сравнивал варианты когда обращение идет к Go серверу напрямую и через Nginx: результат порадовал - среднее время ответа различается буквально на 0.01-0.02 секунды. Что в общем еще раз доказывает что проксирование через Nginx работает очень быстро.

Еще я проводил сравнение при разных GOMAXPROCS: результат фактически не изменился. Чего собственно и следовало ожидать в данных условиях.