Производительность ObjC против MonoTouch и производительность массива

EDIT: добавлена unsafe версия кода C #. Спасибо, ребята за это предложение, unsafe код C # работает быстрее, но только около 3%.


Краткая версия: я написал некоторый контрольный код на C # и в Objective-C и протестировал его на iPad 3. Для версии MonoTouch / C # требуется на 50% -150% больше времени для выполнения, чем тот же код в Objective-C. Вот мой вопрос: могу ли я написать код C #, который выполняется быстрее, чем код, который я использовал для теста (см. Ниже), или это вызвано некоторой присущей разности MonoTouch / Obj-C?


Длинная версия: я написал небольшой прототип для запланированной многоплатформенной игры. После переноса ядра игры из Windows / .NET на iPad 3 / MonoTouch я заметил, насколько медленнее код работает на iPad. Некоторые ключевые части ядра ядра в процессоре iPad в 10 раз медленнее, чем на процессоре Intel (что кажется нормальным, поскольку iPad работает с процессором ARM).

Однако, поскольку это серьезная проблема для нашей игры, я провел небольшой тестовый тест на iPad 3, один раз с MonoTouch , а затем то же самое с простой Objective-C . В тесте есть много простых дополнений с float float и поиска по float массивам. Поскольку MonoTouch GC'ed, я ожидал увидеть небольшую разницу в пользу Obj-C, но, к моему удивлению, для кода MonoTouch требуется гораздо больше времени для запуска, чем код Obj-C. Точнее:

  • Код Obj-C требовал 47'647 ms для запуска в режиме DEBUG и 27'162 ms в режиме RELEASE.
  • Для использования кода MonoTouch без использования unsafe указателей требуется 116'885 ms для запуска в режиме DEBUG и 40'002 ms в режиме RELEASE.
  • Код MonoTouch с unsafe указателями требовал 90'372 ms для запуска в режиме DEBUG и 38'764 ms в режиме RELEASE.

Конечно, режим RELEASE – это то, о чем я забочусь.

Это различие кажется мне немного большим, учитывая тот факт, что MonoTouch компилируется в один и тот же LLVM код LLVM как Obj-C.

Вот код Obj-C, который я использовал:

 int i, j; long time = GetTimeMs64(); float * arr = (float *) malloc(10000 * sizeof(float)); // 10'000 for (j = 0; j < 100000; j++) { // 100'000 arr[0] = 0; arr[1] = 1; for (i = 2; i < 10000; i++) { // 10'000 arr[i] = arr[i - 2] + arr[i - 1]; if (arr[i] > 2000000000) { // prevent arithm. overflow arr[i - 1] = 0; arr[i] = 1; } } } long time2 = GetTimeMs64() - time; 

GetTimeMs64() использует GetTimeMs64() <sys/time.h> .

Здесь мой код C # / MonoTouch в unsafe версии:

 var array = new float[10000]; // 10'000 var watch = System.Diagnostics.Stopwatch.StartNew(); fixed (float* arr = array) { for (int j = 0; j < 100000; j++) // 100'000 { *(arr + 0) = 0; *(arr + 1) = 1; for (int i = 2; i < 10000; i++) // 10'000 { *(arr + i) = *(arr + i - 2) + *(arr + i - 1); if (*(arr + i) > 2000000000) // prevent arithm. overflow { *(arr + i - 1) = 0; *(arr + i) = 1; } } } } watch.Stop(); 

EDIT 2: Это ответ, который мы получили от Xamarin:

В этом конкретном примере есть две проблемы, которые влияют на моноэффективность.

Во-первых, если вы используете компилятор MonoTouch по умолчанию, а не LLVM, вы можете ожидать более низкую производительность, поскольку он настроен на скорость компиляции, а не на скорость выполнения. LLVM даст вам лучшие результаты.

Во-вторых, моно соответствует спецификации ECMA относительно с плавающей запятой и выполняет все вычисления с двойной точностью. Обычно это имеет измеримую стоимость исполнения, особенно по сравнению с C-кодом, использующим поплавки.

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

Как и Марк, вы должны использовать unsafe код, MonoTouch поддерживает эту функцию .NET.

Это приведет к удалению проверок на основе массивов .NET, которые являются приятной и безопасной функцией .NET, но имеют ограничения производительности (поскольку каждый доступ к массиву должен быть проверен).

Это сделает ваш код более привлекательным (как в исходном, так и изначально) выглядит как код Objective-C, и производительность должна быть ближе. Тем не менее я советую вам использовать unsafe код только тогда, когда производительность действительно имеет значение (и после измерения того, что выигрыш стоит того).

  • Как установить Xamarin iOS навигация и цвет строки состояния
  • Правильный способ удаления UIViewController
  • Способ Xamarin для открытия собственной подписной веб-страницы сертификата в UIWebView
  • Добавление изображения в раздел в Monotouch.Dialog
  • Переход MvvmCross ViewModel слева
  • Что такое эквивалентный CGPointZero в Xamarin.iOS?
  • Как работать с перекрывающейся клавиатурой iOs, когда страница уже имеет scrollview в Xamarin Forms
  • Анимированные анимации UIImage не работают в режиме просмотра без анимации
  • Что может заставить UIImageView отображать / отображать только половину загруженного изображения?
  • Образ диска базы данных поврежден в MonoTouch
  • Как уменьшить использование памяти при рендеринге страницы PDF в CGBitmapContext?
  • Interesting Posts

    Преобразование Apple Emoji (String) в UIImage

    AFNetworking обнаруживает, когда Wi-Fi соединение без активного интернет-соединения

    Маркер устройства, получающий Nil

    MDM – APNS не работает

    Альтернатива MFMailComposeViewController?

    Круговая диаграмма с использованием библиотеки диаграмм с iOS swift 3

    Как сравнить символы в пользовательской сортировке sqlite в объекте-c?

    Можно ли ограничить страны, к которым выпущено приложение iOS?

    Как настроить текстовый кернинг с помощью Interface Builder в Xcode 7?

    Распределение памяти iOS – сколько памяти может быть использовано в приложении?

    Использование песочницы APNS в AdHoc Distribution Builds для iOS

    Как зарегистрировать схему URL-адреса для открытия приложения с помощью Xcode 4?

    Как оживить изменение длины и длины сегмента дуги / пончика

    Получить главное окно приложения

    Swift 2.0 – Ошибка построителя событий Google Analytics – NSMutableDictionary не конвертируется в

    Давайте будем гением компьютера.