Статьи

Советы по бенчмаркингу Go + MySQL

Первоначально написал Вадим Ткаченко

Мы только что выпустили в качестве версии с открытым исходным кодом нашего нового percona-agent ( https://github.com/percona/percona-agent ) , агента для работы с Percona Cloud Tools. Этот агент написан на Go .

Я проведу вебинар под названием « Мониторинг всех метрик MySQL с помощью Percona Cloud Tools », который будет посвящен новым функциям Percona-Agent и Percona Cloud Tools, где я также объясню, как он работает. Вы можете зарегистрироваться сейчас и присоединиться ко мне.

Будет много постов о percona-agent, но пока что я хочу посвятить это Go, Go с MySQL и некоторым темам о производительности.

Я давно интересовался языком программирования Go, но в начальных версиях мне не очень понравилась производительность планировщика gorountine. См. Мой отчет более чем два года назад о времени выполнения: уменьшите конкуренцию за планирование в целом$GOMAXPROCS .

Возможно, эта проблема с производительностью была исправлена ​​в Go 1.1, так что сейчас самое время вернуться к моему эксперименту.

Простое выполнение вычисления простых чисел или чисел Фибоначчи в N потоках довольно скучно, поэтому я собираюсь выполнить запросы к Percona Server . Конечно, это добавляет некоторые сложности, поскольку есть больше движущихся частей (например, планировщик go, драйвер sql go, сам MySQL) , но это только делает эксперимент более интересным.

Исходный код моего теста: Go-pk-bench :
Вероятно, это не лучший пример того, как кодировать в Go, но это не было целью этого упражнения. Этот пост действительно о некоторых советах, которые необходимо учитывать при написании приложения на Go с использованием базы данных MySQL (Percona Server) .

Итак, во-первых, нам понадобится драйвер MySQL для Go. Тот, который я использовал два года назад ( https://github.com/Philio/GoMySQL ), довольно устарел. Кажется, самый популярный выбор сегодня — это Go-MySQL-Driver , и именно этот мы используем для внутренней разработки. Этот драйвер основан на стандартном пакете Go «database / sql» . Этот пакет предоставляет стандартный Go-способ для работы с базами данных, подобными SQL. «Database / sql», кажется, работает хорошо, с некоторыми сомнительными дизайнерскими решениями на мой вкус. Таким образом, используя «database / sql» и Go-MySQL-Driver, вам придется иметь дело с некоторыми причудами, такими как почти неуправляемый пул соединений.

Первое, что вы должны принять во внимание, это правильная настройка
runtime.GOMAXPROCS().

Если вы этого не сделаете, планировщик Go будет использовать значение по умолчанию, равное 1. Этот двоичный файл будет использовать один и только один ЦП (так много для современного параллельного языка) .

Команда runtime.GOMAXPROCS(runtime.NumCPU())
предписывает использовать все доступные процессоры. Всегда не забывайте использовать это, если вы заботитесь о многопоточной производительности.

Следующая проблема, с которой я столкнулся в тесте, заключается в том, что когда я запускаю запросы в цикле, т.е. повторяю как можно больше …

rows, err := db.Query("select k from sbtest"+strconv.Itoa(tab+1)+" where id = "+strconv.Itoa(i))

… Очень скоро у нас закончились порты TCP. Очевидно, «database / sql» и Go-MySQL-Driver и его пул интеллектуальных соединений создают НОВЫЕ СОЕДИНЕНИЯ для каждого запроса . Я могу объяснить, почему это происходит, но используя следующее утверждение:

'db.SetMaxIdleConns(10000)'

помогает (надеюсь, кто-то со знанием «database / sql» объяснит, что он делает) .

Таким образом, после этих корректировок мы теперь можем запустить тест, который по запросу, который вы видите, довольно прост — запустить поиск первичных ключей на Percona Server, который, как мы знаем, отлично масштабируется в этом сценарии (я использовал sysbench для создания 64 таблиц по 1 млн строк в каждой, все это подходит в память) . Я собираюсь запустить этот тест с 1, 2, 4, 8, 16, 24, 32, 48, 64 пользовательскими потоками.

Ниже вы можете увидеть графики для MySQL Throughput и CPU Usage (оба графика построены с использованием новых графиков метрик в Percona Cloud Tools )

MySQL Throughput (пользовательские потоки увеличиваются с 1 до 64)
MySQL-Go

Загрузка процессора (пользовательские потоки увеличиваются с 1 до 64)
Cpu-го

Я бы сказал, что результат очень хорошо масштабируется, по крайней мере, он намного лучше, чем два года назад. Интересно сравнить с чем-то, так что есть график от идентичного прогона, но теперь я буду использовать sysbench + lua для основного драйвера рабочей нагрузки.

MySQL Throughput (sysbench, пользовательские потоки увеличиваются с 1 до 64)

MySQL-SysBench

Загрузка процессора (sysbench, пользовательские потоки увеличиваются с 1 до 64)
CPU-SysBench

Из графиков (это то, за что они мне нравятся) мы ясно видим увеличение использования ЦП пользователями (и на самом деле мы можем использовать ЦП на 100% при использовании пользователя + системы), и это явно соответствует увеличению пропускной способности.

И если вы поклонник необработанных чисел:

MySQL Throughput, q/s (more is better)
Threads  | Go-MySQL | sysbench
1	|  13,189	|  16,765
2	|  26,837	|  33,534
4	|  52,629	|  65,943
8	|  95,553	| 116,953
16	| 146,979	| 182,781
24	| 169,739	| 231,895
32	| 181,334	| 245,939
48	| 198,238	| 250,497
64	| 207,732	| 251,972

(человек со знанием Универсального Закона о Масштабируемости может сделать прогноз до 1000 потоков, я оставляю это как домашнее задание)

Итак, в заключение я могу сказать, что Go + MySQL способен показывать приличные результаты, но он все же не так эффективен, как плановый raw C (sysbench) , так как кажется, что он тратит дополнительное системное время на системные вызовы.

Если вы хотите попробовать эти новые графики в Percona Cloud Tools и посмотреть, как они работают с вашей системой — присоединяйтесь к бесплатной бета-версии !