Skip to content

Latest commit

 

History

History
97 lines (70 loc) · 10.1 KB

LOADTEST.md

File metadata and controls

97 lines (70 loc) · 10.1 KB

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

Параметры машины, ОС и инструменты

Тестрирование полностью производилось на машине с 2-х ядерным процессором Intel Core i5-4200H 2.8 ГГц, на котором 4 логических процессора. Память - 8 ГБ. Диск - SSD SATA 6 Гб/c.

3 инстанса БД запускались на localhost (порты 8081, 8082, 8083) на Windows 10 на jre-9.0.1.

Нагрузка подавалась при помощи инструмента yandex-tank (overload), запущенного в виртуальной машине с Ubuntu 16.04.3 LTS, которой было выделено 4 вируальных процессора и 2 ГБ памяти.

Подготовка нагрузки

Для генерации патронов использовался готовый py скрипт из туториала, который принимает на вход строки вида GET||/url||case_tag||body(optional).

Самостоятельно был написан py скрипт для генерации данных, подающихся на вход генератора патронов. Данный скрипт позволяет создать файл с N (только PUT, только GET, смесь PUT и GET) запросами с/без перезаписи и replicas=K/M.

Далее были сгенерированы патроны для всех случаев, описанных в задании.

Тестирование

Описание первой реализации БД.

Исходный проект был примерно таким: для обработки нодой запросов /v0/entity?... от клиента использовался newFixedThreadPool() с 5-ю потоками. Запросы между нодами обрабатывались при помощи newSingleThreadExecutor(), т.к. такие запросы подразумевали чтение и запись с/на диск. После того, как запрос приходил на ноду в newSingleThreadExecutor(), пораждалось еще столько потоков, сколько нод в кластере, чтобы нода могла отправлять данные на другие ноды параллельно. Осуществлено это было при помощи механизма асинхронной работы Future. Нода запросы на другие ноды отправляла параллельно, а ответы принимала последовательно.

Подача нагрузки

Было определено, что БД выдерживает нагрузку примерно 200 GET запросов в секунду и 100 PUT запросов в секунду. Далее подавалась примерно такая нагрузка с replicas 2/3 и 3/3 с/без перезаписи.

Ниже приведена информация о пропускной способности для каждого случая. А более подробная информация с графиками доступна по соответстующим ссылкам.

Описание оптимизаций.

Было решено, что слабые места в первой реализации это:

  1. Использование newSingleThreadExecutor() при обработке запросов, которые пишут/читают на/с диска.
  2. Последовательная обработка ответов от других нод.

В исправленном варианте используется StampedLock для умной блокировки на запись/чтение и для оптимистичного чтения, если запись происходит редко. И вместо однопоточного пула используется newFixedThreadPool() с числом потоков равному Runtime.getRuntime().availableProcessors() + 1.

Вместо Future используются CompletableFuture, которые засчёт колбэков позволяют легко асинхронно обрабатывать ноде ответы от других нод.

Подача нагрузки

По схожему принципу подавалась нагрузка. Пропускная способность выросла в среднем на 30%. Ниже приведены некоторые ссылки на результаты тестирования.

Выводы

Проводить тестирование в таком окружении (БД на host os, а yandex-tank на guest os) было не очень просто. Возникали различные проблемы. И результаты, полученные до и после оптимизаций, кажутся весьма невысокими. Далее в свободное время планируется запустить приложение на разных машинах. И возможно, даже на линуксе, чтобы была возможность профилировать в jvisualvm (на windows нет поддержки профилирования локальных процессов). И посмотреть как разработанная БД поведёт себя в более боевых условиях.

С другой стороны, был получен опыт настройки и использования инструмента yandex-tank, а также были изучены разные механизмы асинхронных вычислений на java. В целом было интересно.