Я натрапив на твердження Xamarin, що їх реалізація Mono на Android та їхніх зібраних програмах C # швидше, ніж код Java. Хтось виконував фактичні орієнтири на дуже схожих кодах Java та C # на різних платформах Android, щоб перевірити такі претензії, міг опублікувати код та результати?
Додано 18 червня 2013 року
Оскільки відповіді не було і не вдалося знайти подібні орієнтири, зроблені іншими, вирішив зробити власні тести. На жаль, моє запитання залишається "заблокованим", тому я не можу розмістити це як відповідь, а лише відредагуйте питання. Будь ласка, проголосуйте, щоб повторно відкрити це питання. Для C # я використовував Xamarin.Android Ver. 4.7.09001 (бета). Вихідний код, усі дані, які я використовував для тестування та складених пакетів APK, містяться на GitHub:
Java: https://github.com/gregko/TtsSetup_Java
C #: https://github.com/gregko/TtsSetup_C_sharp
Якщо хтось хотів би повторити мої тести на інших пристроях чи емуляторах, мені також буде цікаво дізнатися результати.
Результати мого тестування
Я переніс свій клас вилучення речень до C # (з мого додатку @Voice Aloud Reader) і запустив кілька тестів на 10 файлів HTML англійською, російською, французькою, польською та чеською мовами. Кожен запуск виконувався 5 разів на всіх 10 файлах, а загальний час для 3-х різних пристроїв та одного емулятора розміщено нижче. Я протестував лише збірки "Випуск", не включаючи налагодження.
HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM
Java: Загальний загальний час (5 запусків): 12361 мс, із загальним читанням файлів: 13304 мс
C #: Загальний загальний час (5 запусків): 17504 мс, із загальним читанням файлів: 17956 мс
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: Загальний загальний час (5 запусків): 8947 мс, із загальним читанням файлів: 9186 мс
C #: Загальний загальний час (5 запусків): 9884 мс, із загальним читанням файлів: 10247 мс
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: Загальний загальний час (5 запусків): 9742 мс, із загальним читанням файлів: 10111 мс
C #: Загальний загальний час (5 запусків): 10459 мс, із загальним читанням файлів: 10696 мс
Емулятор - Intel (Android 4.2, API 17)
Java: Загальний загальний час (5 запусків): 2699 мс, із загальним читанням файлів: 3127 мс
C #: Загальний загальний час (5 запусків): 2049 мс, із загальним читанням файлів: 2182 мс
Емулятор - Intel (Android 2.3.7, API 10)
Java: Загальний загальний час (5 запусків): 2992 мс, із загальним читанням файлів: 3591 мс
C #: Загальний загальний час (5 запусків): 2049 мс, із загальним читанням файлів: 2257 мс
Емулятор - Arm (Android 4.0.4, API 15)
Java: Загальний загальний час (5 запусків): 41751 мс, загальне читання файлів: 43866 мс
C #: Загальний загальний час (5 запусків): 44136 мс, із загальним читанням файлів: 45109 мс
Коротке обговорення
Мій тестовий код містить в основному аналіз тексту, заміну та пошук Regex, можливо, для іншого коду (наприклад, більше числових операцій) результати були б іншими. На всіх пристроях з процесорами ARM Java працювала краще, ніж код Xamarin C #. Найбільша різниця була в Android 2.3, де C # код працює приблизно в ок. 70% швидкості Java.
На емуляторі Intel (за технологією Intel HAX емулятор працює в режимі швидкого virt), код Xamarin C # запускає мій зразок коду набагато швидше, ніж Java - приблизно в 1,35 рази швидше. Може бути, Mono віртуальні машинні коди та бібліотеки значно краще оптимізовані на Intel, ніж на ARM?
Редагувати 8 липня 2013 року
Щойно я встановив емулятор Genymotion Android, який працює в Oracle VirtualBox, і знову використовується цей власний процесор Intel, а не емуляція процесора ARM. Як і з емулятором Intel HAX, знову C # працює тут набагато швидше. Ось мої результати:
Емулятор Genymotion - Intel (Android 4.1.1, API 16)
Java: Загальний загальний час (5 запусків): 2069 мс, загальна кількість читання файлів: 2248 мс
C #: Загальний загальний час (5 запусків): 1543 мс, із загальним читанням файлів: 1642 мс
Потім я помітив, що відбулося оновлення для бета-версії Xamarin.Android, версія 4.7.11, із примітками до випуску, де згадуються також деякі зміни в режимі виконання моно. Вирішили швидко протестувати деякі ARM-пристрої, і велике здивування - кількість номерів C # покращилася:
BN Nook XD +, ARM (Android 4.0)
Java: Загальний загальний час (5 запусків): 8103 мс, із загальним читанням файлів: 8569 мс
C #: Загальний загальний час (5 запусків): 7951 мс, із загальним читанням файлів: 8161 мс
Оце Так! C # тепер кращий за Java? Вирішив повторити тест на моїй Galaxy Note 2:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: Загальний загальний час (5 запусків): 9675 мс, загальна кількість читання файлів: 10028 мс
C #: Загальний загальний час (5 запусків): 9911 мс, із загальним читанням файлів: 10104 мс
Тут C # здається лише трохи повільнішим, але ці цифри дали мені паузу: Чому час довший, ніж у Nook HD +, навіть якщо у Note 2 є більш швидкий процесор? Відповідь: режим енергозбереження. У Nook його було відключено, на Note 2 - увімкнено. Вирішили протестувати з вимкненим режимом енергозбереження (як і з увімкненим, він також обмежує швидкість процесора):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), енергозбереження відключено
Java: Загальний загальний час (5 запусків): 7153 мс, загальна кількість читання файлів: 7459 мс
C #: Загальний загальний час (5 запусків): 6906 мс, із загальним читанням файлів: 7070 мс
Зараз, на диво, C # трохи швидший, ніж Java на ARM-процесорі. Велике поліпшення!
Редагувати 12 липня 2013 року
Ми всі знаємо, що ніщо не перемагає натурний код за швидкістю, і я не був задоволений виконанням мого роздільника речень на Java або C #, особливо, що мені потрібно його вдосконалити (і тим самим зробити це ще повільніше). Вирішив переписати його на C ++. Ось невеликий (тобто менший набір файлів, ніж попередні тести, з інших причин) порівняння швидкості нативної та Java на моєму Galaxy Note 2 з вимкненим режимом енергозбереження:
Java: Загальний загальний час (5 запусків): 3292 мс, із загальним читанням файлів: 3454 мс
Рідний палець: Загальний загальний час (5 пробіжок): 537 мс, із загальним читанням файлів: 657 мс
Рідна рука: Загальний загальний час (5 пробіжок): 458 мс, загальна кількість читання файлів: 587 мс
Схоже, для мого конкретного тесту нативний код у 6 - 7 разів швидший, ніж у Java. Caveat: не міг використовувати клас std :: regex на Android, тому довелося писати власні спеціалізовані процедури, які шукають розриви абзаців або теги HTML. Мої початкові тести того самого коду на ПК, що використовували регулярний вираз, були приблизно в 4 - 5 разів швидшими, ніж у Java.
Фу! Знову прокинувшись сирою пам’яттю з покажчиками char * або wchar *, я моментально відчув себе на 20 років молодшим! :)
Редагувати 15 липня 2013 року
(Дивіться нижче, із змінами від 30.07.2013, щоб отримати кращі результати з Dot42)
З деякими труднощами мені вдалося перенести свої тести C # на Dot42 (версія 1.0.1.71 бета), іншу платформу C # для Android. Попередні результати показують, що код емулятора Dot42 приблизно в 3 рази (у 3 рази) повільніше, ніж Xamarin C # (v. 4.7.11), на емуляторі Intel Android. Одна з проблем полягає в тому, що клас System.Text.RegularExpressions в Dot42 не має функції Split (), яку я використовував у тестах Xamarin, тому я використовував натомість клас Java.Util.Regex та Java.Util.Regex.Pattern.Split () , тому в цьому конкретному місці в коді є невелика різниця. Однак це не повинно бути великою проблемою. Dot42 компілює код Dalvik (DEX), тому він співпрацює з Java на Android на самому Android, не потребує дорогого інтеропа з C # на Java, як Xamarin.
Тільки для порівняння, я також запускаю тест на пристроях ARM - тут код Dot42 "лише" в 2 рази повільніше, ніж у Xamarin C #. Ось мої результати:
HTC Nexus One Android 2.3.7 (ARM)
Java: Загальний загальний час (5 запусків): 12187 мс, загальне читання файлів: 13200 мс
Xamarin C #: Загальний загальний час (5 запусків): 13935 мс, із загальним читанням файлів: 14465 мс
Dot42 C #: Загальний загальний час (5 запусків): 26000 мс, загальна кількість читання файлів: 27168 мс
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: Загальний загальний час (5 запусків): 6895 мс, із загальним читанням файлів: 7275 мс
Xamarin C #: Загальний загальний час (5 запусків): 6466 мс, із загальним читанням файлів: 6720 мс
Dot42 C #: Загальний загальний час (5 запусків): 11185 мс, із загальним читанням файлів: 11843 мс
Емулятор Intel, Android 4.2 (x86)
Java: Загальний загальний час (5 запусків): 2389 мс, із загальним читанням файлів: 2770 мс
Xamarin C #: Загальний загальний час (5 запусків): 1748 мс, із загальним читанням файлів: 1933 мс
Dot42 C #: Загальний загальний час (5 запусків): 5150 мс, із загальним читанням файлів: 5459 мс
Мені було також цікаво відзначити, що Xamarin C # трохи швидше, ніж Java на більш новому ARM-пристрої та трохи повільніше на старому Nexus One. Якщо хтось хотів би також запустити ці тести, будь ласка, дайте мені знати, і я оновлю джерела на GitHub. Було б особливо цікаво побачити результати справжнього пристрою Android з процесором Intel.
Оновлення 26.07.2013
Просто швидке оновлення, перекомпільоване тестовими програмами з останнім Xamarin.Android 4.8, а також випущеним сьогодні оновленням dot42 1.0.1.72 - суттєвих змін у порівнянні з результатами, про які повідомлялося раніше.
Оновлення 30.07.2013 - кращі результати для dot42
Повторно протестовано Dot42 з портом Роберта (від розробників dot42) мого коду Java на C #. У моєму порту C #, зробленому спочатку для Xamarin, я замінив деякі рідні класи Java, наприклад ListArray, на List клас, який є рідним C # і т. Д. У Роберта не було мого вихідного коду Dot42, тому він знову переніс його з Java і використовував оригінальні класи Java у такі місця, які приносять користь Dot42, я думаю, тому що він працює в Dalvik VM, як Java, а не в Mono, як Xamarin. Зараз результати Dot42 значно кращі. Ось журнал мого тестування:
30.07.2013 - тести Dot42 з більшою кількістю класів Java в Dot42 C #
Емулятор Intel, Android 4.2
Dot42, код Грега за допомогою StringBuilder.Replace () (як у Xamarin):
Загальний загальний час (5 запусків): 3646 мс, загальна кількість читання файлів: 3830 мсDot42, код Грега за допомогою String.Replace () (як у коді Java та Роберта):
Загальний загальний час (5 запусків): 3027 мс, загальна кількість читання файлів: 3206 мсDot42, Код Роберта:
Загальний загальний час (5 запусків): 1781 мс, із загальним читанням файлів: 1999 мсXamarin:
Загальний загальний час (5 запусків): 1373 мс, загальна кількість читання файлів: 1505 мсJava:
Загальний загальний час (5 запусків): 1841 мс, із загальним читанням файлів: 2044 мсARM, Samsung Galaxy Note 2, енергозбереження відключено, Android 4.1.1
Dot42, код Грега за допомогою StringBuilder.Replace () (як у Xamarin):
Загальний загальний час (5 запусків): 10875 мс, загальна кількість читання файлів: 11280 мсDot42, код Грега за допомогою String.Replace () (як у Java та коді Роберта):
Загальний загальний час (5 запусків): 9710 мс, загальна кількість читання файлів: 10097 мсDot42, Код Роберта:
Загальний загальний час (5 пробіжок): 6279 мс, із загальним читанням файлів: 6622 мсXamarin:
Загальний загальний час (5 запусків): 6201 мс, із загальним читанням файлів: 6476 мсJava:
Загальний загальний час (5 запусків): 7141 мс, із загальним читанням файлів: 7479 мс
Я все ще думаю, що Dot42 має пройти довгий шлях. Наявність Java-подібних класів (наприклад, ArrayList) та хороша продуктивність з ними полегшить перенесення коду з Java на C #. Однак це те, що я б, мабуть, багато не робив. Я хотів би скористатися існуючим кодом C # (бібліотеки тощо), який буде використовувати рідні класи C # (наприклад, Список), і це буде повільно працювати з поточним кодом dot42, і дуже добре з Xamarin.
Грег