Подбираем эффективную конфигурацию под ваши нужды
![](https://habrastorage.org/getpro/habr/upload_files/7d1/109/28c/7d110928c627b0d33cea602b85eb2933.png)
Disclaimer. В статье рассмотрим конфигурацию, которую вы можете внедрить в свои проекты. При этом помните про несколько факторов:
• Результат может варьироваться, если используются разные серверные машины.
• Избыток ресурсов — это не всегда хорошо.
• Оптимизация железа должна идти бок о бок с оптимизацией тестов.
Всем привет! Меня зовут Иван Левиков, я старший инженер по тестированию.
ВКонтакте развиваю и ускоряю автотесты, анализирую и улучшаю инфраструктуру, создаю новые решения.
При проектировании инфраструктуры для автотестов на Android приходится искать ответы на вопросы о том, где можно их запускать и где лучше это делать.
Рассмотрим самые популярные места для запуска автотестов:
облачные решения;
решения на физических девайсах.
Облачные решения
В этой категории много предложений от разных компаний, например:
Amazon,
Firebase Test Lab,
Huawei DigiX Lab,
Remote Test Lab от Samsung,
и другие.
Говоря обобщённо, можно выделить такие преимущества и недостатки ферм из облачных решений ↓
![](https://habrastorage.org/getpro/habr/upload_files/555/81c/1cf/55581c1cf8966bce60eb2b609ec9304b.png)
В интернете много обзоров, так что не будем останавливаться на этом.
Если не хотите использовать внешние решения, а стремитесь построить что-то своё, можно обратиться к связке из OpenSTF и физического девайса или к эмуляторам андроид-устройств. Остановимся на каждом варианте чуть подробнее.
OpenSTF + физический девайс
В нашем опыте будет фигурировать Samsung Galaxy S20+ (6 ядер, 8 гигов). По характеристикам это достаточно мощный девайс (см. рейтинг производительности), и его ПО будет обновляться ещё долго. Берём в эксперимент.
![](https://habrastorage.org/getpro/habr/upload_files/800/44d/d5d/80044dd5d444ac72f273bffc9e0d89e0.png)
Так выглядел один из первых прототипов нашей фермы. Собран из смартфонов Samsung, которые питаются через USB hub и подключены к ноутбуку с локально развёрнутой OpenSTF. Можно поиграть в «Отгадай модель устройства по фото».
Так мы и жили довольно долго, управляя физическими девайсами через OpenSTF. При очевидных преимуществах были и сложности — перечисляю их ниже.
![](https://habrastorage.org/getpro/habr/upload_files/cf3/52f/fc2/cf352ffc28f011d40ebc9add7a1ea534.png)
Мы сталкивались с множеством проблем: это, например, очистка данных, закрытие всплывающих окон, падение производительности и непонятные флаки тестов. Если остальные недочёты мы рутинно побеждали, то дебаг и отладка флакующих тестов стали ресурсоёмкими задачами. В одних случаях это было связано с текущим состоянием устройства, а в других — казалось, что с фазой Луны и ретроградным Меркурием.
![](https://habrastorage.org/getpro/habr/upload_files/187/bb1/fcf/187bb1fcfc68f37f5499ece1b5add433.png)
Ферма с виртуальными Android-девайсами
Мы решили провести разные эксперименты, чтобы повысить стабильность. В первую очередь — улучшить нашу ферму, но не за счёт покупки новых физических девайсов, как обычно, а создав параллельно ферму эмуляторов.
![](https://habrastorage.org/getpro/habr/upload_files/3ca/0f4/c8c/3ca0f4c8c407632c0a3ec45131b77104.png)
В итоге мы остановились на конфигурации с виртуальными андроид-девайсами. Начали с построения фермы из связки уже знакомой нам OpenSTF и эмуляторов QEMU. В стандартной комплектации из коробки у наших эмуляторов было по 2 виртуальных ядра и 4 гига оперативной памяти. В целом по производительности и жизнеспособности они нас устраивали. Но для некоторых ситуаций необходимо было создавать собственные решения: например, для превентивного прогнозирования возможной деградации эмулятора и падений тестов из-за этого. Винрейт (соотношение между упавшими и пройденными тестами) в исходном состоянии из коробки в среднем был около 65%, и автотесты при этом находили баги.
![](https://habrastorage.org/getpro/habr/upload_files/e83/a15/796/e83a157969171e4b141c742430aa3296.png)
Ищем оптимальную конфигурацию железа для эмуляторов
Но положение дел меня по-прежнему не устраивало, так что я отправился в длинное приключение в поисках стабильности. Цель: найти оптимальную конфигурацию железа для эмуляторов. Обнаружил пару статей и readme в репозитории Google: там рекомендовали использовать конфиг на 4 виртуальных ядра и 12 гигов оперативной памяти. Мне стало интересно, почему так. А что будет, если дать больше или меньше?
Меня заинтриговали эти вопросы, так что я решил погрузиться в них. Казалось бы, чего здесь долгого — придумать способ для оценки производительности и сравнить между собой несколько конфигураций.
![](https://habrastorage.org/getpro/habr/upload_files/d7c/786/095/d7c786095eaaed2df5aac7d0b1bb6fba.png)
Но всё оказалось не так просто: в процессе работы пришлось делать много анализов производительности, искать причины появления ООМ (Out of memory). Поэтому простым это путешествие было не назвать. Оно стало тем самым «20-minute adventure» — на полгода ????
![](https://habrastorage.org/getpro/habr/upload_files/912/800/a71/912800a713df346ef143d9774d7619e5.png)
Я сравнивал производительность эмуляторов и физических девайсов, чтобы понять, куда мы движемся и не становится ли хуже. Выяснил, что в текущей конфигурации разница во времени прогона автотестов между эмулятором и физическим устройством составляет всего 12%. Может показаться, что это много, но у меня было чёткое ощущение, что мы можем выжать больше. Сейчас расскажу, как мы это сделали!
В начале экспериментов я тестировал много конфигураций серверных машин, которые используются ВКонтакте: начиная от старичков Xeon E5-2680 и заканчивая Xeon Gold 6283. Как это часто бывает, самое крутое железо не всегда было лучшим для наших задач. Так и получилось с Xeon Gold: классной частоты процессора можно было достичь только при срезании части ядер. Иначе под нагрузкой частота могла плавать даже до 0,8 GHz. Плюс существенную роль играет объём кеша уровня L3.
![](https://habrastorage.org/getpro/habr/upload_files/05f/11b/f81/05f11bf8185c0fef3586c02adee33da7.png)
После первых подходов мы оценили результаты и решили остановиться на старом добром E5-2680. Так мы выбрали серверные машины для следующего этапа.
Собирая серверные машины для экспериментов, я сформулировал для себя следующие вопросы ↓
![](https://habrastorage.org/getpro/habr/upload_files/9ae/cab/491/9aecab491da044d4ace6e6758002f52c.png)
Представим, что все машины собраны, эмуляторы подготовлены. Что делать дальше? Правильно, собираем сьют автотестов для оценки производительности, связанных с разными разделами нашего приложения. Так за короткое время получим больше данных, максимально приближенных к реальным.
![](https://habrastorage.org/getpro/habr/upload_files/8ad/1db/858/8ad1db8588331d97f6ee12bdb384db31.png)
За эталон возьмём время прогона на хорошо известном нам физическом устройстве — S20+.
![](https://habrastorage.org/getpro/habr/upload_files/add/bd1/e92/addbd1e92f0d815ceae4320c80437c24.png)
Эмуляторы собраны, конфигурации определены. Начинаем!
На первом этапе мы оценивали изменение времени прогона на каждой из этих конфигураций. В первом туре, в сравнении с S20+, получилась такая таблица.
![](https://habrastorage.org/getpro/habr/upload_files/2a9/285/8cf/2a92858cf0b5c94b5708cc60c55dc255.png)
На подведении недельных итогов спринта мы с командой обсудили показатели и сошлись во мнении, что результаты получаются интересными и надо продолжать эксперименты, расширяя тестируемые значения.
Казалось бы, давайте брать и внедрять самый мощный конфиг, чтобы гонять тесты на 30% быстрее. Но не всё так однозначно, потому что в нашем уравнении до сих пор несколько неизвестных. Копаем дальше!
На разных устройствах и эмуляторах я сталкивался с ситуацией, когда автотест падает, допустим, после шестого беспрерывного прогона. А где-то — после третьего. Или вообще не падает за первые десять прогонов. Это навело меня на мысль, что стабильность автотестов зависит ещё и от конфигурации железа. Эту гипотезу необходимо было проверить, прежде чем двигаться дальше. В результате экспериментов обнаружились такие закономерности падения тестов.
![](https://habrastorage.org/getpro/habr/upload_files/7cc/ef3/0a3/7ccef30a33744887e65bbdebf1b78319.png)
Это выглядит уже интереснее! В наш шорт-лист врываются три конфигурации: 6 ядер, 5 ядер и 4 ядра. Попробуем понять, какая из них может быть нам интересна и почему. Для этого расширим конфигурации в рамках 4 и 5 ядер, докинув эмуляторам оперативной памяти.
![](https://habrastorage.org/getpro/habr/upload_files/213/260/d24/213260d24ca4ac1e7923ee078a573ffc.png)
Неплохо, неплохо. Получается, что нашим минимальным номинантом точно будет конфигурация из 5 виртуальных ядер и 5 или 6 гигов оперативной памяти. Попробуем отталкиваться от этих значений.
Во время прогонов эмуляторы иногда самопроизвольно отключались — и мы ломали над этим голову. Детально изучили логи и графики из мониторинга и поняли, что это банальное ООМ. Значит, эмулятору недостаточно N гигов оперативной памяти, которое мы выделяем ему?
Да, всё так. Когда создаётся более мощный конфиг, потребляется больше ресурсов — так что для беспроблемной работы нужно резервировать ещё больше, чем мы выделяем. В процессе прогона автотестов наши эмуляторы разгонялись не сразу, а постепенно, при этом иногда уходя резко вверх. С помощью экспериментов мы поняли, что для спокойного существования эмуляторам желательно закладывать дополнительные ресурсы: минимум 1,5 гига оперативной памяти и 1 ядро vCPU плюсом к уже выделенным. Это пригодится для java heap и нужд пода. А в целом такое решение позволит сгладить скачки, увеличит жизнеспособность эмуляторов и обезопасит вас от нестабильности в тестах из-за железа.
Что внедряем в итоге (и что при этом учитываем)
Мы останавливаемся на базовом внедрении конфига эмулятора в 6 VCPUS / 6 GB и добавляем сверху минимум 1,5 гига оперативной памяти. По расчётам ожидаем, что в сравнении с нынешним конфигом эмулятора новый позволит нам ускориться на 20% и больше. А главное, он повысит стабильность прогонов автотестов — и мы будем увереннее в них.
Дальше коротко поделюсь выводами.
Вот о чём важно не забыть, когда внедряете конфиг в своём проекте ↓
![](https://habrastorage.org/getpro/habr/upload_files/e0f/229/b8d/e0f229b8d50411ef1564aaf78f4dc5cf.png)
А вот что стоит учесть, планируя эксперименты:
Можно отталкиваться от конфигурации с 5 или 6 виртуальными ядрами для мощного эмулятора и от 5,5 гигов RAM под эмулятор.
Разрыв между ядрами начал уменьшаться после 5 ядер (разница между 5 и 6 около 1,5 %).
Увеличение ОЗУ на 1 гигабайт даёт ускорение до + 0,5%.
Избыток ресурсов — это не всегда хорошо.
При изменении в железе эти значения тоже могут стать другими.
Какие конфигурации используете и во сколько потоков запускаете тесты? Поделитесь в комментариях.
А если хотите прокачивать автотесты в нашей команде — смотрите вакансии здесь.
Будем ВКонтакте!
Комментарии (9)
MLGcode
18.01.2022 15:44Спасибо за статью. Хотелось бы уточнить какую версию приложения запускали на эмуляторе и какую версию запускали на S20? Не связан ли рост производительности с запуском x86 версии вместо ARM?
Kreatif74 Автор
18.01.2022 16:23Добрый день
Хотелось бы уточнить какую версию приложения запускали на эмуляторе и какую версию запускали на S20
На эмуляторах используется x86_64, а на физ девайсе ARM
Вы правы, что рост может быть связан с многими факторами, в том числе и использованием разной архитектуры. Я проверял эту гипотезу создавая эмуляторы с разными ABI - с x86_64 и с arm64_v8a. К сожалению, пока что результаты особо не впечатляют в плане цифр и было принято решение остановиться на x86_64.
Но в этой стороне я еще эксперементирую :)
HSerg
20.01.2022 23:23На x86_64-эмуляторе можно запускать собранные для arm приложения. Сам производительность не замерял, но есть упоминания, что работает быстрее arm-эмулятора.
Segrey646
Благодарю, интересная статья.
Вопрос: в процессе подбора эмуляторов, Вам удалось найти хороший open source эмулятор? Чтобы использовать для домашних заготовок и мелких тестов
Elian
Судя по отсылкам на доку Google, использовался docker image от собственно Google с тем же эмулятором, что и в Android Studio.
us-docker.pkg.dev/android-emulator-268719/images/30-google-x64:latest
Segrey646
благодарю Вас, на досуге изучу
Kreatif74 Автор
Да, можно отталкиваться от образа, который предоставляет Google, но его желательно дорабатывать, чтобы снизить размеры (мы сократили вес исходного образа в 4 раза) и выключить все то, что не нужно тестам
Kreatif74 Автор
Добрый день
Мне кажется, все продукты хороши по своему, главное корректно использовать)
Например, для личных потребностей можно использовать эмулятор, встроенный в андроид студию, как пишет Elian в комментарии ниже
Если есть желание и время, чтобы разбираться с запуском докера или вам необходимо поднять продукт для многих пользователй - в этом случае можно использовать docker image от Google или другие решения с docker-image и подготовленными эмуляторами, которые можно взять на GitHub
Segrey646
Благодарю Вас, теперь буду знать по крайней мере еще 2 решения, для решения задач различной сложности