PMetrium Native — тестуємо продуктивність мобільних додатків

Усі статті, обговорення, новини про тестування — в одному місці. Підписуйтеся на QA DOU!

Привіт, я Микола Панасюк, QA Tech Lead в компанії Parimatch Tech. Я відповідаю за автоматизацію функціонального тестування, розробку фреймворків та інструментів для проведення нефункціонального тестування.

Разом з Performance QA Engineer Павлом Майкшаком ми розробили «PMetrium Native» — інструмент для проведення тестування продуктивності мобільних додатків.

Ця публікація буде однаково корисна як для досвідчених Native Developers, так і для початківців разом з QA Engineers, які готові подивитися на мобільні додатки під іншим кутом.

Homo sapiens та смартфони

Ще декілька років тому важко було уявити, що життя більшості людей зміниться докорінно. Не буде звичних масових заходів, роботи в офісі з понеділка по п’ятницю, вщент набитих людьми автобусів, а зображувати Homo sapiens будуть не з палицею, а зі смартфоном.

У наше життя нахабно увірвався COVID-19, а тепер ще й загарбницька війна росії проти України. Ці та багато інших факторів зробили смартфон майже незамінним для кожного. Тепер за допомогою мобільного додатку можна, не виходячи з дому, замовити їжу, подивитися фільм, провести відеоконференцію та перерахувати гроші на ЗСУ.

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

Нам потрібен був інструмент, який би дозволив отримувати метрики продуктивності (завантаженість центрального процесору (CPU), обсяг оперативної пам’яті (RAM), швидкість передачі даних мережею (Bytes/s), розрядку батареї (mAh) і т.д.) як зі самого смартфону, так і цільового мобільного додатку, а потім порівняти ці дані з тим, що відбувалося власне на смартфоні.

Що пропонував ринок

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

Потім знайшли Apptim — це певною мірою вже було ближчим до того, що ми шукали. Apptim працює як окремий інструмент, який не вимагає інтеграції в кодову базу мобільного додатку, взаємодіє як з Android-, так і з iOS-девайсами. Попрацювавши з ним деякий час, зрозуміли, що нам не вистачає гнучкості в певних моментах, тож це не зовсім те, чого ми шукали. Інтеграція в CI була доступна лише за використання ентерпрайз підписки, що коштувала значних грошей. Ми навіть спробували написати в службу підтримки Apptim, щоб отримати детальнішу консультацію, але вони так і не вийшли на зв’язок.

Звісно були і залишаються також стандартні механізми і підходи, які безпосередньо пропонують системи IDE для профайлингу мобільного додатку, але вони більше про «перевірити і пофіксити тут і зараз», коли про проблему вже відомо. Ми ж хотіли інструмент, який легко було б інтегрувати в СІ/CD.

Якщо відверто, у нас спершу були завищені очікування. Раніше ми успішно інтегрували в наші pipelines Sitespeed.io — Open Source tool, який збирає метрики продуктивності інтернет-сайтів (на мою суб’єктивну думку, найкращий Open Source інструмент, що я коли-небудь бачив). Ми очікували, що знайдемо щось подібне і для мобільних додатків.

Реальність виявилася не такою, як нам хотілося. Якщо ринок server-side і client-side тестування продуктивності вже досить зрілий, то цього не скажеш про тестування продуктивності мобільних додатків. Інформації було вкрай мало. Тож так, ми вирішили писати свій власний «велосипед» — PMetrium Native — інструмент для проведення тестування продуктивності мобільних додатків.

Створення PMetrium Native

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

  • робота з платформами Android та IOS;
  • відсутність інтеграції в код мобільного додатку;
  • відсутність потреби ручної взаємодії для збору метрик;
  • проста інтеграція в функціональні автоматизовані тести за необхідності;
  • проста інтеграція в CI/CD;
  • простий доступ до метрик, їх чітка структура та візуалізація;
  • стабільність та надійність.

Щоб не братися за все та відразу, беручи до уваги, що в жодного з нас не було необхідної експертизи для тестування продуктивності мобільних додатків, окрім як досвіду з server-side та client-side, ми вирішили їсти слона частинами.

Почали ми з Android-платформи, як більш відкритої та гнучкої для такого роду експериментів. За декілька тижнів у нас уже був на руках перший прототип інструменту, а вже під кінець червня 2022 року вийшов перший внутрішній реліз PMetrium Native, за який уже було принаймні не соромно.

Тут потрібно зробити невеликий ліричний відступ та зауважити, що на момент написання цієї колонки ми випустили PMetrium Native як Open Source Software (OSS) тільки для Android-платформи, тому наразі ділимося досвідом та прикладами реалізації інструменту саме для цієї операційної системи. Проте ми активно працюємо над реалізацією для iOS-платформи, що стане доступною в PMetrium Native вже зовсім скоро разом з додатковим функціоналом для Android.

Ви можете спитати «А чому тоді стаття виходить зараз, а не коли уже все готово? Принаймні під Android та iOS.» Питання закономірне, а відповідь на нього проста — ніколи не буде вдалого часу. Постійно буде щось із backlog по функціоналу, що хочеться обов’язково доробити, і от тоді вже буде класненько. А «класненько» потребує часу, ретельного аналізу, розробки і тестування. Крім того, ми дуже любимо світ OSS та маємо надію, що наш інструмент стане комусь у пригоді.

PMetrium Native під мікроскопом

Архітектура

Давайте вже нарешті розбиратися, що ж таке цей наш PMetrium Native. Пропонуємо поглянути на логічну діаграму (мал. 1). Фіолетовим кольором виділено ті логічні елементи, які існують і без PMetrium Native, також добре відомі для будь-якої команди розробки мобільних додатків. Оранжевим кольором виділені ті елементи, які привносить наш інструмент разом зі своїми супутниками.

Мал. 1. Логічна діаграма PMetrium Native (зображення за автором)

PMetrium Native являє собою web host, який має відкритий RESTful API для взаємодії. Він повинен хоститися на Workstation, іншими словами, на робочій машині чи навіть на ноутбуці, який має фізичний доступ до мобільних девайсів, щоб мати можливість з ними взаємодіяти і знімати метрики продуктивності.

Результати своєї роботи, тобто метрики, інструмент зберігає в Time-series database — InfluxDB. Далі все, що залишається, — візуалізувати зібрані метрики. Ми вибрали для цього Grafana, адже для нас це де-факто стандарт.

Зазначу, що надалі під PMetrium Native матиметься на увазі PMetrium Native host, InfluxDB та Grafana.

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

PMetrium Native пропонує запустити збір до початку виконання тесту та зупинити по його завершенню (зелений та червоний блоки відповідно). До речі, у випадку iOS-девайсів процесна діаграма виглядатиме практично таким же чином.

Мал. 2. Процесна діаграма PMetrium Native (зображення за автором)

Практичне використання

Настав час продемонструвати, як все ж таки зняти метрики продуктивності з Android девайсу та й самого мобільного додатку за допомогою PMetrium Native. Припустимо, що у вас уже є один автоматизований функціональний тест. Наприклад, він відкриває додаток, ви потрапляєте на домашній екран, а потім переходите в інший екран. Далі вам потрібно звернутися до API PMetrium Native наступним чином:

> curl -G -d "device=ADB_DEVICE_NAME" -d "app=APPLICATION_NAME" http://localhost:7777/Start
> dotnet test .\src\PMetrium.Native\FunctionalTests --filter ColdStart
> curl -G -d "device=ADB_DEVICE_NAME" http://localhost:7777/Stop

де:

  • ADB_DEVICE_NAME — назва девайсу, отримана через команду adb devices;
  • APPLICATION_NAME — ім’я мобільного додатку, який буде аналізуватися.

Зауважимо, що взаємодія з мобільним додатком можлива напряму. Також варто зазначити, що утиліта curl тут для прикладу, можна вільно використовувати http клієнтів силами відповідного тестового фреймворку. Детальніше про PMetrium Native, його API та деталі реалізації можна дізнатися з репозиторію на GitHub.

Після проведення тесту відбудеться автоматична обробка метрик, а результат всієї роботи буде доступним як візуалізація на Grafana Dashboard (мал. 3).

Мал. 3. Візуалізація метрик від PMetrium Native (джерело — Grafana)

Варто прокоментувати декілька речей, які видно з візуалізації:

  • PMetrium Native збирає як метрики самої системи, так і метрики самого мобільного додатку, але є можливість легко відключити/включити збір тих метрик, які вас цікавлять силами API;
  • вертикальні лінії — це анотації від Grafana;
    • зелена анотація — момент часу, коли почався збір метрик;
    • червона анотація — момент часу, коли закінчився збір метрик;
    • сині анотації — події (events), які відбуваються при взаємодії з додатком;
  • PMetrium Native підтримує роботу з багатьма мобільними девайсами одночасно, це означає, що можливий запуск тестів паралельно на декількох приладах;
  • завдяки зручним фільтрам Grafana Dashboard, можна з легкістю знайти той запуск, що вас цікавить;
  • дві нижні панелі виводять часові метрики подій, що трапилися при роботі вашого додатку. Вони якраз таки і відображені у вигляді синіх анотацій;
  • за замовчуванням PMetrium Native збирає всі доступні метрики, які він вміє визначати, те ж саме стосується подій в додатку.

Тепер варто трохи детальніше зупинитися на синіх анотаціях, що зображають події в мобільному додатку. Звідки вони беруться і для чого вони нам взагалі потрібні? Під час збору метрик продуктивності виникає бажання зрозуміти, чому в певний момент часу, наприклад, зросла активність центрального процесора чи використання мережі.

Саме для відповіді на такі запитання і встановлення відповідності між активністю в мобільному додатку і показниками метрик PMetrium Native використовує події, які можна сконфігурувати в мобільному додатку. І, так, тут уже потрібна інтеграція в код мобільного додатку, хоча це суперечить одній з наших початкових умов, але це не є обов’язковим для нормальної роботи PMetrium Native. Тому це варто розглядати як додатковий бонус для тих, хто завжди хоче більшого.

Для Android-платформи достатньо додати в код вашого мобільного додатку один рядок, який би відповідав певній події під час його роботи (таких подій може бути декілька). Він створить запис в logcat (механізм логування для Android-додатків):

LogWrapper.d(PERFORMANCE_TESTING, "Some event" + System.currentTimeMillis())

де:

  • LogWrapper.d() — просто назва методу, який у вас може бути іншим, головне, щоб він виводив лог у logcat.
  • PERFORMANCE_TESTING — обов’язкова назва тегу для логу.
  • "Some event" — довільна зрозуміла для вас назва події.
  • System.currentTimeMillis() — час у мілісекундах в Unix форматі.

У результаті в logcat повинні з’явитися зафіксовані події і PMetrium Native їх з легкістю вичитає та опрацює:

05-17 16:47:16.183 30844 30844 D PERFORMANCE_TESTING: Some 1st event 1652795236183
05-17 16:47:19.955 30844 30844 D PERFORMANCE_TESTING: Some 2nd event 1652795239955
05-17 16:47:24.763 30844 30844 D PERFORMANCE_TESTING: Some 3rd event 1652795244763
05-17 16:47:28.014 30844 31253 D PERFORMANCE_TESTING: Some 4th event 1652795248014
05-17 16:47:42.784 30844 31170 D PERFORMANCE_TESTING: Some 5th event 1652795262784
05-17 16:47:44.649 30844 30844 D PERFORMANCE_TESTING: Some 6th event 1652795264649

Зазначимо, що для iOS-платформи концепція буде схожою, але вона наразі ще не фіналізована.

Але як все-таки ми знімаємо метрики продуктивності у випадку Android платформи? PMetrium Native — OSS, тому потрібно одразу покласти всі карти на стіл. У випадку Android-платформи ми намагалися використати весь наявний арсенал. Оскільки операційна система (OS) Android базується на звичному для нас Linux ядрі, ми отримали можливість підключитися до термінала самого девайсу, викликати потрібні нам команди і отримати певну метрику тут і зараз.

Якщо цю команду помістити в цикл і запустити з певною періодичністю, скажімо, раз в секунду (насправді, в середньому раз в 0,9 секунди, даючи час на виконання самій команді), то вийде елементарна система моніторингу. На практиці виходить, що при виклику API на /Start PMetrium Native підключається до телефону через протокол ADB, передає shell скрипт (phoneMetrics.sh) у внутрішню пам’ять самого девайсу та запускає його, а по закінченню тесту при виклику API на /Stop зупиняє його виконання. Усі зібрані метрики збережені у текстових файлах у внутрішній пам’яті девайсу.

Після цього текстові файли з метриками проходять процес зчитування та обробки. Усі оброблені метрики PMetrium Native зберігає в InfluxDB. Для прикладу приведу фрагмент коду з самого скрипту:

# Frames of the app

if [ $FRAMES_APP = "yes" ]
then
    while [ $(cat $TEST_STATUS_FILE) = "started" ] && [ ! -z $(pidof $APP_NAME) ]
	do 
		dumpsys gfxinfo $APP_NAME | grep -C 3 "50th percentile" >> $FRAMES_APP_FILE
		echo "$(date +%s)\n" >> $FRAMES_APP_FILE
		sleep 0.9
	done &
fi
FRAMES_APP_PID=$!

Вище показана лише та частина коду, яка збирає метрики по фреймах від мобільного додатку, адже весь скрипт надто великий, щоб виводити його тут повністю. Як можна помітити, для метрики по фреймах ми використали утиліту dumpsys, детальніше про яку можна почитати на офіційній сторінці. Більшість метрик, які PMetrium Native збирає по самому мобільному додатку, отримані завдяки тій же утиліті dumpsys, але вона не зовсім підходить для збору метрик самої операційної системи, тут вже нам допомагають такі утиліти як:

  • /proc/meminfo — для доступу до RAM системи;
  • top — для доступу до CPU системи.

Окремо варто зупинитися на метриках активності мережі. У першій версії PMetrium Native може обробити метрики мережі лише самого мобільного додатку, але не через утиліту dumpsys, а завдяки використанню утиліти Nethogs.

Такий підхід має свої недоліки:

  • для роботи Nethogs потребує ROOT доступ до системи, що мало кому підійде;
  • за нашими спостереженнями, він добре справляється з класичними додатками по типу інтернет-магазинів, але не зміг зняти метрики з додатка YouTube, тобто не завжди працює так, як того очікуєш.

Але є й хороші новини: ми знайшли спосіб отримувати метрики через мережу самого додатку і системи набагато кращим способом, і без ROOT доступу. Ця можливість з’явиться у релізі другої версії PMetrium Native разом з підтримкою iOS-платформи.

Також не можемо не згадати про те, що у репозиторії PMetrium Native на GitHub ви знайдете директорію Localhost, в якій знаходиться все необхідне для швидкого запуску в Docker потрібної інфраструктури (наприклад, InfluxDB та Grafana з мінімальним набором обов’язкових налаштувань). Звісно, що у межах однієї статті важко розповісти про всі можливі деталі та необхідні умови для повноцінного запуску PMetrium Native, тому ми підготували та виклали вичерпну документацію на тому ж таки GitHub.

Було б неправильно з нашого боку не згадати про недоліки інструменту, для когось вони будуть суб’єктивними, для когось — об’єктивними:

  • автори PMetrium Native при його створенні використовували лише наявні в них знання та інструменти, тому цілком закономірно, що багато чого можна було б зробити краще, оптимальніше і т.д.;
  • у випадку Android-платформи скрипт для збору метрик потребує також системних ресурсів, що за нашими замірами складає 10-16% від часу CPU (залежить від фізичних характеристик самого девайсу), хоча й використання ресурсів рівномірне на всій часовій шкалі. Маємо надію поліпшити цей показник. Лайфхак від нас — просто відключити збір непотрібних метрик, щоб зменшити навантаження на систему;
  • для збору подій в мобільному додатку вам все ж потрібно вносити зміни в код;
  • необхідність ROOT доступу для мережевих метрик у першій версії інструменту.

Післяслово

Хоча все, на перший погляд, виглядає просто та зрозуміло, хай це не вводить вас в оману. За цією «простотою» ховається багато проблем, які ми вирішували як інженери, а також десятки і сотні годин людської праці.

Окремо хочу висловити подяку Антону Бойко, який повірив у цей інструмент, зробив вагомий внесок у його створення та вивід в OSS. Будемо відверті: не всі проблеми ще вирішені, але ми завзято над цим працюємо, так само як і над розширенням функціонала.

На наш погляд, ринок тестування продуктивності мобільних додатків ще не зрілий, як мінімум, кількість сторінок пошуку в Google про це красномовно свідчить. Ми зі свого боку прагнемо зробити його бодай на крок, але кращим. Віримо, що у нас це вийде разом з великою силою OSS.

Звісно будуть інженери, яким сподобається наш інструмент, а комусь у ньому не вистачатиме функціоналу. Також будуть і кращі експерти за нас, які знайдуть безліч недоліків у PMetrium Native, але конструктивна критика дозволить нам зробити інструмент кращим. Що ж «c’est la vie», як кажуть французи.

Сподіваюся, що читач не дуже стомився, отримав задоволення від прочитаного матеріалу і зрозумів, що ж таке цей наш PMetrium Native для тестування продуктивності мобільних додатків. Це все, що ми підготували для вас у першій версії PMetrium Native. "Далі — більше!"©

Сподобалась стаття? Натискай «Подобається» внизу. Це допоможе автору виграти подарунок у програмі #ПишуНаDOU

👍ПодобаєтьсяСподобалось7
До обраногоВ обраному1
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Я подібну штуку робив, але ресурсів не вистачило продовжити та завершити. Ідея була побудувати систему трекінга перформансу на базі будь якої системи логгуваня, з подальшою відправкою у систему для обробки. У мене не було настільки детальних вимог щодо логування системної інформації, хотів моніторити інформацію по мінімуму — за скільки проходить сплеш, час на ініціалізацію додатка, завантаження даних з беку і тд і тп.

Шкода, що розробники мобільних ОС не дають ніяких зручних API для цього, потрібно вгризатись зубами, збирати інфу по дрібничкам і так далі.

Так, не надто великий арсенал API для такої роботи. Проте на IOS уже є подібний, описаний вами API, на основі «os-signpost»

To record and view your signposts, open your project in Xcode and choose Product > Profile to launch Instruments.

от тут як раз і проблема як на мене, як отримати ці дані з умовних 10-20 різних моделей, проганяючи UI тести на фермі у стороннього вендора? Я не копав, але на перший погляд штука працює тільки у зв’язку з XCode. Андроіда це так само стосується.

У PMetrium Native v2.0 я саме підготую реалізацію автоматизації для збору метрик без необхідності запуску XCode, там не буде застосовано os-signpost (принаймні поки що), але підходи мають бути зрозумілі

Підписатись на коментарі