Спосіб швидкого вимірювання продуктивності випадкового сервера

У світі веб-розробки часто виникає завдання підбору сервера під веб-додаток, або по-аналогії перевірка продуктивності наявного сервера. Можливо, нам необхідно купити новий сервер, щоб він витримував передбачуване навантаження. Може бути, замовник передає нам для деплоя свій наявний сервер. У будь-якому випадку, якщо після розгортання і запуску програми вона буде показувати низьку продуктивність, то запитають з команди.

Основна проблема в тому, що виконати оцінку продуктивності сервера потрібно швидко, без використання спеціальних (читай, складних) інструментів і, зрозуміло, до релізу. Ми повинні вміти зняти з сервера якісь метрики і, помноживши їх на відомі показники програми, отримати оцінку продуктивності програми на цьому сервері.

В житті виконати цю задачу може далеко не кожен розробник, а з решти далеко не кожен хоче її виконувати.

У цій статті я хочу розповісти про ті прийоми і інструменти, які ми використовуємо для оцінки продуктивності сервера.

Типові ситуації

№1
Команда розробників виходить на реліз і скоро готується випустити першу версію продукту. Наступний крок — розгорнути додаток на бойовому сервері, який за умовами проекту потрібно купити і налаштувати. На загальному мітингу керівник проекту пропонує знайти відповідального для вирішення цього «простого» питання: «Так хто підбере хостинг і сервер? Я закладу необхідну суму в бюджет наступної ітерації». Як правило, бажаючих на цю задачу немає :). Більш того, пряме делегування — «Вася, займися цим завданням!» — теж не працює: Вася миттєво знаходить і перераховує не менше десятка термінових/важливих завдань, які ось прямо зараз на ньому висять і здати їх потрібно учора («і взагалі, ми — не адміни»). Корячись загальному почуттю самозбереження, команда злагоджено підказує Керівнику Проекту, де саме потрібно пошукати такого спеціаліста (не ближче, ніж в сусідньому підрозділі), і ось вже Він точно підбере ідеальну конфігурацію сервера.

№2
За умовами проекту сервер надає замовник. Це виглядає як відмінне умова на старті проекту, але воно не є таким, коли ми підходимо до релізу. На питання клієнта «А сервер-потужний?» слід незмінний відповідь: «А!». Після деплоя Керівник Проекту сумними очима дивиться на таймінги відгуків веб-додатки. З'являються неприємні думки «Хто винен?» і «Що робити?». Приходить розуміння того, що конфігурацію сервера потрібно було підбирати самим, але, з іншого боку, фахівець з сусіднього підрозділу так і не знайшовся. За фактом виходить, що цей потужний сервер — дешева VPS'ка, параметри якої виглядають добре, але вона ділить ресурси хоста з армією своїх побратимів-сусідів. Клієнт оплатив сервер на п'ять років вперед :) і міняти що-небудь не збирається (раніше потрібно було говорити).

№3
Адвансед-рівень — у клієнта є сервер і адмін. Параметри сервера не викликають нарікань, але після деплоя програми ми бачимо страшні гальма, лаги, затримки. Наш девелоперський сервер за параметрами в три рази слабкіше, але програма працює у вісім разів швидше. Жодна з наших пропозицій про заміну сервера або купівлю нового не приймається, так як у адміна свою думку — гальмує «ваше» додаток. Клієнт не знає, кому вірити; ідея, що несе нові витрати, йому теж не подобається, тому аргумент адміна зараховується. Керівник Проекту вимагає від команди чіткого пояснення «чому додаток гальмує» і доказів з цифрами «провини» сервера. У команди, як завжди, повно вільного часу, тому всі з задоволенням беруться за вирішення завдання і ставлять пиво фахівця з сусіднього відділу за підказку «куди копати».

Резюмуємо, з якими ситуаціями ми стикаємося і які завдання потрібно вміти вирішувати:

— Підбір сервера під програму і навантаження
— Оцінка можливостей наявного сервера
— Вміти відповісти на питання «Чому так повільно?»

Вимоги до інструментів вимірювання

Найбільш точний спосіб вимірювання продуктивності сервера є одночасно і найбільш очевидним: потрібно встановити додаток на сервер і активувати реальне навантаження. Такий спосіб хоч і дає точний результат, але є марним :) з ряду причин:

  • Ми хочемо знати оцінку сервера заздалегідь, до запуску в продакшн.
  • Метод вимірювання повинен бути швидким і дешевим.
  • Інструмент вимірювання повинен бути простим у використанні і установці на сервер.
  • Результат вимірювання повинен бути легко интерпретируемым і порівнюваним.

Об'єкт вимірювання

Сервер куплений, операційна система встановлена, sshd запущений. Відкриваємо консоль і входимо на сервер. Чорна консоль, зелені букви і миготливий курс німо запитують тебе: «Що далі?». Саме час замислитися, що будемо вимірювати і з чого складається продуктивність.

До цього моменту питання здавався простим: «запущу який-небудь бенчмарк і все буде ясно». Зараз, при вигляді миготливого курсору консолі, думка завмерла і ніяк не може видати необхідну команду.

Від чого більшою мірою залежить продуктивність веб-додатки:

  • Швидкість роботи зв'язки CPU + RAM
  • Швидкість дискової підсистеми
  • Продуктивність середовища виконання мови (в нашому випадку це PHP)
  • Налаштування бази даних (у нас це MySQL або PostgreSQL)
  • І, звичайно, від самого додатка (від того, які ресурси вона використовує)
Нам потрібно мати чотири інструменти, які б могли заміряти швидкість роботи окремо:

  • для компонентів сервера: CPU+RAM і Дискова підсистема
  • для програмних компонентів: MySQL і PHP
Маючи на руках результати вимірів, ми можемо комплексно говорити про продуктивність сервера в цілому, а також можемо прогнозувати роботу веб-додатки.

Інструменти вимірювань

sysbench
github.com/akopytov/sysbench

Описати інструмент краще, ніж це зробив автор, не можна, тому цитую:

SysBench is a modular, cross-platform and multi-threaded benchmark tool for evaluating OS parameters that are important for a system running a database under intensive load.
The idea of this benchmark suite is to quickly get an impression about system performance without setting up complex database benchmarks or even without installing a database at all.
Це то, що потрібно! Sysbnech дозволяє швидко отримати уявлення про продуктивність системи без установки складних бенчмарків і спеціальних інструментів.

Встановити sysbench просто:

apt-get install sysbench


Можна скомпілювати:

$ ./autogen.sh


$ ./configure


$ make 


Перевіряємо продуктивність CPU
Для цього запускаємо обчислення двадцяти тисяч простих чисел.

$ sysbench --test=cpu --cpu-max-prime=20000 run


За замовчуванням обчислення буде виконуватися в одному потоці. Використовуємо ключ --num-threads=N, якщо хочемо проводити паралельні обчислення.

Результат роботи тіста:

Тест CPU:
Test execution summary:
total time: 17.3915 s
total number of events: 10000

total time taken by event execution: 17.3875
per-request statistics:
min: 1.66 ms
avg: 1.74 ms
max: 4.00 ms
approx. 95 percentile: 2.03 ms

Найцікавіше в цьому тесті — це значення total time. Запускаючи цей тест на декількох серверах, ми можемо порівнювати свідчення.

Наведу приклад запуску цього тесту на тих серверах, які були у мене під рукою в момент підготовки статті.



Примітки:

  • G2 приблизно в три рази швидше, ніж A3
  • Проста VPS'ка на регру за 250 руб/міс порівнянна з G2 :)
  • Виртуалка на базі Xeon X3440 відпрацювала так само, як і NUC i5
  • Дивує однаковість результатів на чотирьох серверах
  • Можливо, обчислення простих чисел відбувається на одних і тих же блоках CPU, які не відображають загальної продуктивності процесора
Тестуємо дискову підсистему
Перевірка дискової підсистеми виконується в три кроки:

  • Підготувати (згенерувати) набір тестових файлів
  • Виконати тестування, зняти показники
  • Прибрати за собою сміття
Підготовка тестових файлів:

$ sysbench --test=fileio --file-total size=70G prepare


Команда створить набір файлів загальним розміром на 70 гігабайт. Розмір повинен помітно перевершувати обсяг оперативної пам'яті, щоб на результат тестування не впливав кеш операційної системи.

Виконання тесту:

$ sysbench --test=fileio --file-total size=70G --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 run


Буде проведений тест в режимі випадкового читання (rndw) протягом 300 секунд, після чого будуть показані підсумки. Знову таки, за замовчуванням тестування буде виконуватися в одному потоці (Number of threads: 1).

Очищення тимчасових файлів:

$ sysbench --test=fileio cleanup


Приклад результат виконання тесту:

Тест FileIO:
Operations performed: 249517 Read, 166344 Write, 532224 Other = 948085
Read 3.8073 Gb Written 2.5382 Gb Total transferred 6.3455 Gb (21.659 Mb/sec)
1386.18 Requests/sec executed

Test execution summary:
total time: 300.0045 s
total number of events: 415861
total time taken by event execution: 178.9646
per-request statistics:
min: 0.00 ms
avg: 0.43 ms
max: 205.67 ms
approx. 95 percentile: 0.16 ms

Threads fairness:
events (avg/stddev): 415861.0000/0.00
execution time (avg/stddev): 178.9646/0.00

В якості міри продуктивності дискової підсистеми можна використовувати значення середньої швидкості передачі даних (у даному прикладі це 21.659 Mb/sec).

Подивимося, що показав цей тест на моїх серверах:

image

Примітки:

  • Кидаються в очі підозріло низькі значення швидкості на всіх випробуваних серверах
  • На NUC i5 встановлений ssd диск, скільки б разів я не запускав тест, значення швидкості передачі даних завжди було в інтервалі від 1.5 до 2 Mb/sec
  • На моєму робочому MacBook Pro 2015 з ssd значення швидкості в цьому тесті одно 140Mb/sec 8-)
Тест MySQL OLTP
Тест перевіряє швидкість виконання транзакцій MySQL сервера, причому кожна транзакція складається як із запитів на читання, так і на запис.

Дуже зручно змінювати параметри сервера в my.cnf, перезапускати його і проганяти серію тестів, — відразу видно, як змінюється продуктивність.

Підготовка до тестування:

$ sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=test --mysql-user=root --mysql-password=pass prepare


Запуск тесту:

$ sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=test --mysql-user=root --mysql-password=pass --max-time=60 --oltp-read-only=off --max-requests=0 --num-threads=8 run


Параметр --oltp-read-only можна встановити в значення on, тоді будуть виконуватися тільки запити на читання, що дає змогу оцінити швидкість роботи СУБД в режимі, наприклад, slave-бази.

Результат виконання тесту:

OLTP test statistics:
queries performed:
read: 564158
write: 0
other: 80594
total: 644752
transactions: 40297 (671.57 per sec.)
deadlocks: 0 (0.00 per sec.)
read/write requests: 564158 (9402.01 per sec.)
other operations: 80594 (1343.14 per sec.)

Test execution summary:
total time: 60.0040 s
total number of events: 40297
total time taken by event execution: 479.8413
per-request statistics:
min: 1.14 ms
avg: 11.91 ms
max: 70.93 ms
approx. 95 percentile: 15.54 ms

Самий цікавий параметр в звіті — це кількість транзакцій в секунду (transactions per sec).

Як цей тест показав себе на серверах:



Примітки:

  • На всіх серверах конфігурація MySQL була однакова
  • Дивує відсутність істотних відмінностей між серверами A3 і G2
  • NUC i5 порівняємо з G2

Як виміряти продуктивність PostgreSQL?

На жаль, інструмент sysbench не має вбудованих засобів для тестування PostgreSQL. Але це зовсім не заважає, так як можна використовувати утиліту pgbench.

Додаткова інформація:
www.postgresql.org/docs/devel/static/pgbench.html

Дефолтний сценарій тестування продуктивності багаторазово виконує наступну операцію:

BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, delta, CURRENT_TIMESTAMP);
END;

Для створення тестових даних виконуємо команду:

$ pgbench -h localhost -U test_user -i -s 100 test


Виконуємо тестування:

$ pgbench -h localhost -U test_user -t 5000 -c 4 -j 4 test


Ключі команди означають, що 4 клієнта будуть виконувати 5000 транзакцій в 4 потоки. В результаті буде виконано 20000 транзакцій.

Результат:

starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 10
query mode: simple
number of clients: 4
number of threads: 4
number of transactions per client: 5000
number of transactions actually processed: 20000/20000
latency average: 0.000 ms
tps = 3350.950958 (including connections establishing)
tps = 3357.677756 (excluding connections establishing)

Найголовніше тут — це tps.

Порівняльних тестів на різних серверах, на жаль, немає :)

А як же продуктивність PHP?

Вдосталь награвшись з sysbench і намотавши кіловати енергії на CPU багатьох серверів, ми навчилися швидко і досить адекватно оцінювати продуктивність випадково взятої сервера, що, в свою чергу, дозволяє нам давати експертний прогноз продуктивності web-додатки на цьому сервері.

Однак виникають ситуації, коли sysbench показав хороший результат, а php-додаток на цьому сервері демонструє абсолютно посередні показники продуктивності.

Зрозуміло, на результат впливають такі параметри, як:

  • Версія PHP
  • Наявність акселератора
  • Як і чим скомпільовано PHP
  • Які розширення активовані
Дуже хотілося б мати інструмент, який би легко встановлювався і після запуску видавав зрозумілу метрику продуктивності поточного PHP на сервері. Причому, хотілося, щоб цей інструмент не впливала продуктивність дискової підсистеми (або мережевий) — вимірюємо лише роботу інтерпретатора PHP на зв'язці Процесор+Пам'ять.

Просте гугление/роздум привело до думки, що:

  • Існуючого інструменту немає
  • Потрібно написати свій еталонний алгоритм (скрипт)
  • чинності незмінності алгоритму отримані результати можна порівнювати
Що і було зроблено: github.com/florinsky/af-php-bench

Скрипт зібраний у phar-архів, що помітно полегшує його завантаження та запуск на довільному сервері.

Мінімальна версія PHP для запуску — 5.4.

Для запуску:

$ wget https://github.com/florinsky/af-php-bench/raw/master/build/phpbm.phar


$ php phpbm.phar


Скрипт виконує десять тестів, розділених на три групи:

  • Перша група — це загальні операції (цикли, rand, створення/видалення об'єктів)
  • Друга група тестів перевіряє рядкові функції, implode/explode, обчислення хешів
  • Третя — робота з масивами
  • Всі виміри виконуються в секундах
Звіт про виконання тесту:

[GENERAL]
1/10 Cycles (if, while, do) ...................... 6.72 s
2/10 Generate Random Numbers ..................... 3.21 s
3/10 Objects ..................................... 4.82 s
Time: 14.76 .. 

[STRINGS]
4/10 Simple Strings Functions ................... 13.09 s
5/10 Explode/Implode ............................ 15.90 s
6/10 Long Strings ............................... 30.37 s
7/10 String Hash ................................ 23.57 s
Time: .. 82.93

[ARRAYS]
8/10 Fill arrays ................................ 22.32 s
9/10 Array Sort (Integer Keys and Values) ....... 17.17 s
10/10 Array Sort (String Keys and Values) ........ 14.29 s
Time: 53.79 .. 

TOTAL TIME: . 151.47

Скрипт дозволяє не тільки оцінити загальну продуктивність PHP на даному сервері (total time), але і побачити, з чого вона складається. Неодноразово бачив, що посередній загальний результат складався тільки з одного тіста: десь це може бути повільна робота генератора випадкових чисел, а де-то робота з довгими рядками.

На сторінці результатів (https://github.com/florinsky/af-php-bench/blob/master/RESULTS.md) я записував одержувані звіти і групував їх у загальну таблицю. Іноді результати дивують :)

Висновок

Я б хотів додати, що зазначені вище інструменти дозволяють оцінити продуктивність сервера лише прямо зараз, у момент виміру. Необхідно розуміти, що на роботу сервера можуть впливати паралельно працюючі процеси. І якщо замір показав хороший результат, це не означає, що він буде таким завжди.

Особливо гостро ця проблема проявляється, якщо ви аналізуєте сервер клієнта, який вже експлуатується «в повний зріст». Ви не знаєте, які cron-завдання виконуються, які процеси дрімають і чекають свого події, щоб включити довгий gzip/tar, ще тут працює антивірус/спам-фільтр і десяток виртуалок, в яких відбувається загадкове.

Для аналізу поведінки сервера часу нам допомагають atop і iostat. Збираємо статистику за кілька днів (або більше), після чого можна переглянути.

atop
Запис даних у файл:

$ atop -w /tmp/atop.raw 1 60


Читати запис:

atop -r /tmp/atop.raw


iostat
Завмер завантаження CPU:

$ iostat -c 1


Висновок:

%user %nice %system %iowait %steal %idle
82.21 0.00 17.79 0.00 0.00 0.00
79.05 0.00 20.70 0.00 0.00 0.25
80.95 0.00 19.05 0.00 0.00 0.00
80.95 0.00 19.05 0.00 0.00 0.00
80.85 0.00 18.91 0.25 0.00 0.00
...

Завмер завантаження дискової підсистеми:

$ iostat -xd /dev/sda 1


Висновок:

rkB/s wkB/s await r_await w_await svctm %util
0.00 2060.00 4.05 0.00 4.05 3.98 95.60
0.00 2000.00 3.97 0.00 3.97 3.95 96.40
0.00 1976.00 3.92 0.00 3.92 3.92 95.60
0.00 2008.00 3.95 0.00 3.95 3.93 96.00
0.00 2008.00 3.92 0.00 3.92 3.92 96.80
0.00 2020.00 4.03 0.00 4.03 4.00 97.60
0.00 2016.00 3.97 0.00 3.97 3.97 97.20
...

І, зрозуміло, можна використовувати Munin і йому подібні, щоб збирати статистику з сервера в довгому хронологічному порядку.

Спасибі за увагу!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.