Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Сопоставление продуктивности Xamarin (monodroid) и Java (DalvikVM) на Android устройствах

Anna | 17.06.2014 | нет комментариев
Добродушный день. Многие интересуются насколько крепко отличается эффективность Xamarin на Android либо iOS. Вопрос с iOS я пока оставлю открытым, а вот все вопросы по продуктивности monodroid предлагаю закрыть раз и навечно.

Нередко эти вопросы вызваны из-за неправильного понимания как устроен monodroid, мне скажем задавали вопросы типа «А Xamarin потом пересобирается под JVM?». Это безусловно же не так. Значимо понимать, что Xamarin выполняется на том же ярусе Android где работает виртуальная машина Android Dalvik. Следственно при сопоставлении продуктивности мы на деле имеем сопоставление результативности работы 2-х виртуальных машин: Mono VM и Dalvik VM.

Методология проверки

Для проверки продуктивности нужен реализованный на Java и общепринятый способ, тот, что нужно будет реализовать на C#. Я решил применять знаменитый тест продуктивности LINPACK в первую очередь потому что его начальный код открыт и легко будет реализовать C# версию, а во-вторую — есть теснее готовая Android версия LINPACK for Android написанная на Java.

Тест продуктивности LINPACK это способ оценки продуктивности путем оценки скорости выполнения операций с плавающей точкой вычислительной системы. Бенчмарк сделан Джеком Донгарра (Jack Dongarra) и измеряет как стремительно компьютер ищет решение плотной СЛАУ Ax = B размерностью N x N способом LU-декомпозиции. Решение получено способом Гаусса с выделением основного элемента (изложение), при котором выполняется 2/3*N3 2*N2 операций с плавающей точкой. Итог определяется в Floating-point Operations Per Second(MFLOP / s, Почаще легко FLOPS). Сам тест продуктивности был описан в документации к фортрановской библиотеке линейных вычислений LINPACK и с тех пор его вариации применяются, скажем, для составления рейтинга TOP500 суперкомпьютеров.

Реализация

Невзирая на достаточно примитивную задачу я решил реализовывать ее согласно выработанному мной гайдлайну на кроссплатформенную разработку.

На первом шаге строим кроссплатформенное решение:

Потом согласно образцу проектирования MVP создаем Presenter и View
image
Пишем тесты и реализуем Presenter через тест. Для этого я использую NUnit и NSubstitute. Описывать NUnit специального смысла нет, на мой взор больше комфортного фреймворка для тестирования легко нет. NSubstitute это весьма комфортный фреймворк для создания заглушек на основании интерфейсов. Фреймворки устанавливаются через NuGet.

Маленький пример применения NSubstitute из доков

// Let's say we have a basic calculator interface:
    public interface ICalculator
    {
        int Add(int a, int b);
        string Mode { get; set; }
        event Action PoweringUp;
    }
// We can ask NSubstitute to create a substitute instance for this type. We could ask for a stub, mock, fake, spy, test double etc., but why bother when we just want to substitute an instance we have some control over?
    _calculator = Substitute.For<ICalculator>();
// Now we can tell our substitute to return a value for a call:
    _calculator.Add(1, 2).Returns(3);
    Assert.That(_calculator.Add(1, 2), Is.EqualTo(3));
// We can check that our substitute received a call, and did not receive others:
    _calculator.Add(1, 2);
    _calculator.Received().Add(1, 2);
    _calculator.DidNotReceive().Add(5, 7);
// If our Received() assertion fails, NSubstitute tries to give us some help as to what the problem might be:
    NSubstitute.Exceptions.ReceivedCallsException : Expected to receive a call matching:
        Add(1, 2)
    Actually received no matching calls.
    Received 2 non-matching calls (non-matching arguments indicated with '*' characters):
        Add(1, *5*)
        Add(*4*, *7*)

// We can also work with properties using the Returns syntax we use for methods, or just stick with plain old property setters (for read/write properties):
    _calculator.Mode.Returns("DEC");
    Assert.That(_calculator.Mode, Is.EqualTo("DEC"));
    _calculator.Mode = "HEX";
    Assert.That(_calculator.Mode, Is.EqualTo("HEX"));

В нашем случае вначале создаем Setup способ

[TestFixtureSetUp]
public void Setup()
{
      view = Substitute.For<ILinpackView>();
      presenter = newLinpackPresenter(view);
}

И исполняем легкой тест, безусловно асинхронно

 [Test]
 public void CalculateAsyncTest()
 {
       presenter.CalculateAsync().Wait();
       Assert.That(view.Mflops, Is.EqualTo(130.0).Within(5).Percent);            
 }

Сторонним ПО я узнал что эффективность моего ПК — около 130 MFLOPS/s, так что его и впишем в ожидаемые значения, добавив погрешность.

Внутри способа у меня создание асинхронной Task и заполнение View. Все легко и ясно

public Task CalculateAsync()
{
    Linpack l = new Linpack();
    return Task.Factory.StartNew(() => l.RunBenchmark())
        .ContinueWith(t =>
        {                    
            _view.Mflops = l.MFlops;
            _view.NormRes = l.ResIDN;
            _view.Precision = l.Eps;
            _view.Time = l.Time.ToString();
        }
        );
}

Программа реально реализована, ни строчки платформозависимого кода пока написано не было. Сейчас создаем Android план:

визуальный конструктор внутри Visual Studio дозволит нам стремительно и легко накидать нужное приложение и посмотреть как оно выглядит с различными темами. Правда, так как ни одна из тем не была применена к Activity то на устройстве мы получим вид по умолчанию

Сейчас остается только скомпилировать релиз, подписать его приложенным к студии мастером и установить на устройства с поддержкой консольной утилиты adb.exe

Незадолго я приметил, что скорость выполнения кода зависит не только от Debug/Release но и от подключения устройства по USB. Происходит это из-за того что при подключенном телефоне в режиме разработки Android гонит громадные объемы отладочной информации на компьютер, что может повлиять на скорость выполнения операций (а может и не повлиять), исключительно если есть конструкции логирования типа Trace. Следственно отключаем устройства и запускаем тесты.

Готово!

Итог

У меня два тестовых устройства, HTC Desire с Android 2.3 (Qualcomm QSD8250, 1000 МГц, 512 ОЗУ) и Fly IQ443 с Android 4.0.4 (MediaTek MT6577, 1000 МГц, 512 ОЗУ)

Вот их итоги:
HTC Desire:

Fly IQ443:

И прекрасные графики

Итог

Итоги теста показывают что работа Mono на Android как минимум сравнима, а изредка и превосходит эффективность Dalvik, но в целом они приблизительно равны. 2-й столбец некорректен, т.к. Mono самосильно распараллелил тест на два ядра без каких либо действий с моей стороны, предполагаю где-то на ярусе Task’ов, в то время как для Linpack for Android нужно очевидно предпочесть мультипоточный тест.

Кстати говоря, данный план показывает отличия в размерах для релизовых сборок. Java версия теста весит каждого лишь 280Кб, когда Monodroid версия весит примерно 2.3 МБ на один тип процессора (armeabi и armeabi-v7), т.е. в сумме 4.6 МБ, что однако в условиях современных сетей не кажется мне особенно критичным. Если такой размер apk кажется вам неприемлемым дозволено отдельно собрать и распространять пакеты для armeabi и armeabi-v7, благо Google Play разрешает загружать различные apk для различных платфом.

Начальный код приложения находится тут

P.S. Мне бы хотелось собрать статистику по устройствам. Так что если у кого есть Android и 10 минут свободного времени буду дюже признателен если вы измерите эффективность вашего устройства с поддержкой LINPACK for Android и опять сделанной MonoLINPACK и запишите итог сюда (если у вас многоядерный процессор выбирайте сразу Run Multiple Thread в LINPACK for Android)

P.P.S. Подобный тест для iOS будет

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB