Давайте протестируем ваше решение, не догадываясь! Тогда посмотрите, есть ли реальное улучшение?

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

Довольно часто было несколько способов улучшить производительность, и большинство из них было достигнуто путем экспериментов. Могут возникнуть вопросы, например, если я воспользуюсь этим алгоритмом, получу ли я лучшую производительность? Или, если я буду использовать эту библиотеку вместо другой, будет ли какая-то существенная разница? На эти вопросы можно было ответить без предположений или ручного тестирования, выполнив сравнительный анализ.

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

Начните с базового

Начнем с простого примера. Напишите этот код в main.gofile.

Мы определили простую функцию, которая имитирует определенную операцию, для завершения которой требуется время, в данном случае это случайная длительность от 0 до 100 миллисекунд. Просто и легко!

Теперь перейдем к коду тестирования. Вы можете записать это в main_test.go файле. Помните, что тестирование производительности похоже на любой другой тестовый код.

Вы можете запустить тест, набрав go test -bench=.. Но, делая это, вы не только запускаете тестовый код, вы также запускаете тестовый код (если он у вас есть).

Вы можете отфильтровать тест, чтобы убедиться, что он будет запускать тестовый код, только запустив go test -bench=Bench. Потому что все тестовые функции нужно запускать с Bench. Точно так же, как вы определяете тестовые функции со словомTest в начале имени функции. Если вы хотите быть более конкретным, вы можете указать флаг -bench с именем вашей тестовой функции, например go test -bench=BenchmarkCalculate.

По умолчанию функция тестирования запускается не менее 1 секунды. Если второй не истек, когда функция Benchmark возвращается, значение b.N увеличивается в последовательности 1, 2, 5, 10, 20, 50,… и функция запускается снова.

Вы можете указать продолжительность тестирования с помощью команды go test -bench=. -benchtime=20s. Эта команда заставляет сеанс тестирования занять 20 секунд.

Тестирование приложения RestAPI

Мы продолжим использовать нашу старую Calculate функцию и использовать ее в приложении RestAPI. Кроме того, будет дополнительная функция, которая имитирует тяжелую операцию с именем CalculateSlow. Теперь давайте изменим наш main.go файл.

Это приложение очень простое. Он просто содержит одну конечную точку, которая использует Calculate и CalculateSlow. Мы должны указать x и y в качестве строки запроса, тогда мы получим результат.

Как насчет кода тестирования?

Конечно, более длинный код по сравнению с тем, который у нас был. Я объясню это по крупицам.

  • Вы можете запустить код, как и раньше. Но теперь у нас есть 3 тестовых функции. Запустив команду go test -bench=Bench -benchtime=5s. Вы получите что-то похожее на это:

  • Если установлен флаг -benchtime=5s, каждая тестовая функция будет выполняться не менее 5 секунд.
  • Обратите внимание, что мы определили переменную уровня пакета result для хранения результата, полученного от API. Все это сделано для того, чтобы избежать оптимизации компилятора и исключения тестируемой функции, которая искусственно снижает время выполнения теста.
  • Если вы измените порядок функций теста, например, BenchmarkCalculateRestAPI1 определяется первым, вы получите тот же результат. Вы видите значительную разницу между первой тестовой функцией и второй из-за случайного целого числа.
  • Увидев этот результат, вводимые значения один, сто один миллион не имеют никакого значения. Вы увидите это лучше, удалив случайное целое число в Calculate функции.

Это оно? Можем ли мы сделать наш код лучше? Давайте поищем решение, например, использовать goroutine наверное?

Делаем это лучше

Можем ли мы улучшить наш код, используя замечательную функцию, которую нам предоставил Go, а именно goroutine. Давайте разберемся.

Запустив команду go test -bench=Bench -benchtime=5s, вы получите аналогичный результат:

Видите ли, поскольку Calculate и CalculateSlow работают одновременно, мы получаем лучший результат. Обратите внимание, что для каждой тестовой функции мы получаем примерно 2 секунды - продолжительность сна, которую мы определили в CalculateSlow. Это определенно хорошее решение для реализации.

Вывод

Мы начали с простого примера на реальный случай, а затем улучшили предыдущий код, добавив лучшее решение.

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

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

Спасибо за чтение и удачного кодирования!

Другие статьи, похожие на эту статью: