Написать эту статью меня побудило мнение, что xamarin – это что-то неповоротливое, большое, долго загружается (при сравнении с нативными инструментами разработки) и при это нельзя написать проект в стиле «write once – run everywhere» как это предлагают инструменты типа PhoneGap. К сожалению, я обратил внимание на Xamarin совсем недавно поэтому допускаю возможность, что раньше оно было большим и тормозным. Давайте же подробнее взглянем как обстоят дела на текущий момент c Xamarin.Android.
Как оно работает?
Не буду подробно на этом останавливаться, достаточно популярно это описано на официальном сайте ну или в этой статье на хабре. Важно лишь понимать, что это не какой-то там инструмент над Dalvik – это полноценная альтернатива. Хорошо понятно это из этой популярной картинки.
Это означает, что в теории оно работает не хуже «родных» приложений. На практике же приложениям на Xamarin приходится таскать за собой свой рантайм и пользоваться peer-объектами для связи с JVM. Посмотрим как это влияет на производительность.
Размер приложения
Понятное дело, что приложение будет весить больше чем аналог на нативном инструменте разработки под конкретную платформу т.к. xamarin тянет за собой рантайм, но давайте же узнаем его размер на примере Android “Hello world” приложения с одной кнопкой и TextView. Здесь нам поможет Linker, который просто вырежет всё, что нам не нужно (к сожалению, он слегка туповат и может вырезать нужное, поэтому иногда можно увидеть что-то вроде такого в проектах: LinkerPleaseInclude.cs или xml-конфиги) и в итоге apk с Hello world станет весить менее 2 Мб (с включенным AOT) — по-моему, это очень даже неплохо.
Сравнение производительности
Для тестирования использовались следующие устройства:
- Samsung Galaxy S3 (как один из самых популярных Android смартфонов)
- Samsung Galaxy Tab (x86 архитектура)
- Asus Nexus 7 2013 (как устройство, на котором можно включить ART вместо Dalvik)
Тесты прогонялись несколько раз для вычисления среднего (подробнее – смотрите код) результата. В Android Studio собиралась релизная подписанная apk, в Xamarin – release с включенным полным линкером + AOT (хотя я не заметил разницы с ним и без).
Прежде чем мы начнем гонять какие-нибудь непонятные тесты в стиле вычисления миллионного знака в числе «пи» я хотел бы просто по-обывательски показать то, что интересует пользователя непосредственно – это скорость запуска и плавность пролистывания большого списка элементов. Ведь именно это раздражает лично меня в приложениях написанных на инструментах типа PhoneGap – ты покупаешь топовый смартфон с 4-8 ядрами чтобы видеть лагающую прокрутку на не особо сложных формах и долгий запуск. Буду рад добавить в видео вариант на PhoneGap или Titanium если кто-нибудь напишет ;-).
Как видно из видео, простое приложение на JAVA стартует (холодный старт) практически моментально, в то время как Xamarin имеет задержку в одну секунду – в принципе не так страшно, но раунд записываем за JAVA. В реальных приложениях скорость загрузки даже на JAVA может занимать бОльшее время, и разница в одну секунду будет скорее как погрешность – все равно придется показывать сплэшскрин. Плавность скроллинга одинаково хорошая, хотя в аналогичном примере на Windows Phone она была бы ещё плавнее ;-). Далее проведем серию сферических в вакууме тестов дабы вбросить холиварчик:
1. Арифметические операции
Просто набор каких-то операций с числами, в том числе перемножения чисел с плавающей точкой.
Исходник на JAVA
Исходник на C#
Результаты (числа здесь и далее – время выполнения в миллисекундах)
Выводы:
1) Честно говоря, я ожидал что Xamarin на x86 проявит себя лучше, а тут плачевный результат.
2) На обычном arm устройстве результаты примерно одинаковые
3) Включение ART на Nexus 7 почти в 1.5 раза ускорило выполнение теста!
2. Работа с коллекциями
В этом тесте мы просто создаем коллекцию контейнеров, которую затем фильтруем по определенном признаку и получаем на выходе новую коллекцию.
Исходник на JAVA
Исходник на C#
Выводы:
На самом деле этот тест – просто укол в больное место JAVA в которой нет custom value types (ключевое слово struct в C#). Но интересен результат на ART – почти в 2 раза быстрее Dalvik. Но не стоит воспринимать это как шутку – разрабатывая игры на Xamarin мы не раз получали солидный прирост производительности заменив классы на структуры.
3. Работа со строками
Тут мы создаем очень большую строку, над которой выполняем некоторые действия.
Исходник на JAVA
Исходник на C#
Выводы:
Тест показывает, что работа со строками более эффективна в Xamarin (хотя стоило ещё посмотреть на память), опять же на ART результаты лучше. Что интересно, изначально в тесте не использовался StringBuilder (в обоих платформах) и разница была просто колоссальной в пользу Xamarin.
В качестве заключения...
Совершенно точно не стану утверждать, что Xamarin – лучшее средство для разработки под Android – это далеко не так. Тут и ещё мало функциональная IDE, в которой сложно разрабатывать интерфейс для андроид из-за отсутствия подсказчика – приходится писать его в Android Studio, а потом пользоваться секретной техникой copy-paste, благо java и C# уж очень “похожи” ;-), иногда отваливается отладчик (на некоторых устройствах с определенной версией ОС), а если глянуть в багзиллу то от некоторых открытых багов может стать не по себе. Но темпы развития и возможность писать общую кроссплатформенную логику позволяют закрыть на это глаза и писать быстрые и отзывчивые приложения (камень в огород PhoneGap) под все платформы.
Репозиторий с тестами тут. Уже кто-то даже сделал пул-реквест на добавление варианта с MvvmCross :-).
Автор: Nagg