Natknąłem się na twierdzenia Xamarin, że ich implementacja Mono na Androidzie i aplikacje kompilowane w języku C # są szybsze niż kod Java. Czy ktoś przeprowadził rzeczywiste testy porównawcze na bardzo podobnym kodzie Java i C # na różnych platformach Android, aby zweryfikować takie twierdzenia, mógł opublikować kod i wyniki?
Dodano 18 czerwca 2013 r
Ponieważ nie było odpowiedzi i nie mogłem znaleźć takich testów wykonanych przez innych, postanowiłem zrobić własne testy. Niestety moje pytanie pozostaje „zablokowane”, więc nie mogę opublikować tego jako odpowiedzi, tylko edytować pytanie. Głosuj, aby ponownie otworzyć to pytanie. Do C # użyłem Xamarin.Android Ver. 4.7.09001 (beta). Kod źródłowy, wszystkie dane, których użyłem do testowania, oraz skompilowane pakiety APK znajdują się w GitHub:
Java: https://github.com/gregko/TtsSetup_Java
C #: https://github.com/gregko/TtsSetup_C_sharp
Jeśli ktoś chciałby powtórzyć moje testy na innych urządzeniach lub emulatorach, chciałbym również poznać wyniki.
Wyniki z moich testów
Przeniesiłem moją klasę wyodrębniania zdań do C # (z mojej aplikacji @Voice Aloud Reader) i przeprowadziłem testy na 10 plikach HTML w języku angielskim, rosyjskim, francuskim, polskim i czeskim. Każde uruchomienie przeprowadzono 5 razy na wszystkich 10 plikach, a całkowity czas dla 3 różnych urządzeń i jednego emulatora podano poniżej. Testowałem tylko kompilacje „Release”, bez włączonego debugowania.
HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM
Java: Całkowity czas całkowity (5 uruchomień): 12361 ms, całkowity odczyt pliku: 13304 ms
C #: Całkowity czas całkowity (5 uruchomień): 17504 ms, z całkowitym odczytem pliku: 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: Grand całkowity czas (5 uruchomień): 8947 ms, z całkowitym odczytem pliku: 9186 ms
C #: Całkowity czas całkowity (5 uruchomień): 9884 ms, z całkowitym odczytem pliku: 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: Całkowity czas całkowity (5 uruchomień): 9742 ms, z całkowitym odczytem pliku: 10111 ms
C #: Całkowity czas całkowity (5 uruchomień): 10459 ms, z całkowitym odczytem pliku: 10696 ms
Emulator - Intel (Android 4.2, API 17)
Java: Całkowity czas całkowity (5 uruchomień): 2699 ms, całkowity odczyt pliku: 3127 ms
C #: Całkowity czas całkowity (5 uruchomień): 2049 ms, z całkowitym odczytem pliku: 2182 ms
Emulator - Intel (Android 2.3.7, API 10)
Java: Całkowity czas całkowity (5 uruchomień): 2992 ms, całkowity odczyt pliku: 3591 ms
C #: Całkowity czas całkowity (5 uruchomień): 2049 ms, z całkowitym odczytem pliku: 2257 ms
Emulator - Uzbrojenie (Android 4.0.4, API 15)
Java: Całkowity czas całkowity (5 uruchomień): 41751 ms, całkowity odczyt pliku: 43866 ms
C #: Całkowity czas całkowity (5 uruchomień): 44136 ms, całkowity odczyt pliku: 45109 ms
Krótka dyskusja
Mój kod testowy zawiera głównie parsowanie tekstu, zastępowanie i wyszukiwanie Regex, być może dla innego kodu (np. Więcej operacji numerycznych) wyniki byłyby inne. Na wszystkich urządzeniach z procesorami ARM Java działała lepiej niż kod Xamarin C #. Największa różnica występowała w systemie Android 2.3, w którym kod C # działa w przybliżeniu. 70% prędkości Java.
Na emulatorze Intel (z technologią Intel HAX, emulator działa w trybie szybkiego podglądu), kod Xamarin C # uruchamia mój przykładowy kod znacznie szybciej niż Java - około 1,35 razy szybciej. Może kod i biblioteki maszyn wirtualnych Mono są znacznie lepiej zoptymalizowane na Intelie niż na ARM?
Edytuj 8 lipca 2013 r
Właśnie zainstalowałem emulator Genymotion Android, który działa w Oracle VirtualBox, i ponownie ten używa natywnego procesora Intel, nie emulując procesora ARM. Podobnie jak w przypadku emulatora Intel HAX, ponownie C # działa tutaj znacznie szybciej. Oto moje wyniki:
Emulator Genymotion - Intel (Android 4.1.1, API 16)
Java: Całkowity czas całkowity (5 uruchomień): 2069 ms, całkowity odczyt pliku: 2248 ms
C #: Całkowity czas całkowity (5 uruchomień): 1543 ms, całkowity odczyt pliku: 1642 ms
Następnie zauważyłem, że nastąpiła aktualizacja Xamarin.Android beta, wersja 4.7.11, z uwagami do wydania, w których wspomniano również o niektórych zmianach w środowisku wykonawczym Mono. Postanowiłem szybko przetestować niektóre urządzenia ARM i wielka niespodzianka - poprawiono liczby C #:
BN Nook XD +, ARM (Android 4.0)
Java: Całkowity czas całkowity (5 uruchomień): 8103 ms, całkowity odczyt pliku: 8569 ms
C #: Całkowity czas całkowity (5 uruchomień): 7951 ms, z całkowitym odczytem pliku: 8161 ms
Łał! C # jest teraz lepszy niż Java? Postanowiłem powtórzyć test na mojej Galaxy Note 2:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: Całkowity czas całkowity (5 uruchomień): 9675 ms, całkowity odczyt pliku: 10028 ms
C #: Całkowity czas całkowity (5 uruchomień): 9911 ms, z całkowitym odczytem pliku: 10104 ms
Tutaj C # wydaje się być tylko nieco wolniejszy, ale te liczby zatrzymały mnie: Dlaczego czas jest dłuższy niż w Nook HD +, mimo że Note 2 ma szybszy procesor? Odpowiedź: tryb oszczędzania energii. W Nook został wyłączony, w Note 2 - włączony. Podjęto decyzję o przetestowaniu z wyłączonym trybem oszczędzania energii (podobnie jak przy włączonym, ogranicza także prędkość procesora):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), wyłączono oszczędzanie energii
Java: Całkowity czas całkowity (5 uruchomień): 7153 ms, całkowity odczyt pliku: 7459 ms
C #: Całkowity czas całkowity (5 uruchomień): 6906 ms, z całkowitym odczytem pliku: 7070 ms
O dziwo, C # jest również nieco szybszy niż Java na procesorze ARM. Duża poprawa!
Edytuj 12 lipca 2013 r
Wszyscy wiemy, że nic nie przebije natywnego kodu szybkości i nie byłem zadowolony z wydajności mojego rozdzielacza zdań w Javie lub C #, szczególnie, że muszę go poprawić (a tym samym spowolnić). Postanowiłem przepisać go w C ++. Oto małe (tj. Mniejszy zestaw plików niż poprzednie testy, z innych powodów) porównanie prędkości natywnej i Java na moim Galaxy Note 2, z wyłączonym trybem oszczędzania energii:
Java: Całkowity czas całkowity (5 uruchomień): 3292 ms, całkowity odczyt pliku: 3454 ms
Natywny kciuk: Całkowity czas całkowity (5 uruchomień): 537 ms, całkowity odczyt pliku: 657 ms
Uzbrojenie rodzime: Całkowity czas całkowity (5 uruchomień): 458 ms, całkowity odczyt pliku: 587 ms
Wygląda na to, że w moim konkretnym teście natywny kod jest 6-7 razy szybszy niż Java. Zastrzeżenie: nie mogłem używać klasy std :: regex na Androidzie, więc musiałem napisać własne specjalistyczne procedury szukające podziałów akapitów lub tagów HTML. Moje pierwsze testy tego samego kodu na komputerze PC przy użyciu wyrażenia regularnego były około 4 do 5 razy szybsze niż Java.
Uff! Ponownie budząc surową pamięć wskaźnikami char * lub wchar *, od razu poczułem się 20 lat młodszy! :)
Edytuj 15 lipca 2013 r
(Zobacz poniżej, z edycjami 30.07.2013, aby uzyskać znacznie lepsze wyniki z Dot42)
Z pewnym trudem udało mi się przenieść moje testy C # na Dot42 (wersja 1.0.1.71 beta), kolejną platformę C # dla Androida. Wstępne wyniki pokazują, że kod Dot42 jest około 3 razy (3 razy) wolniejszy niż Xamarin C # (wer. 4.7.11) na emulatorze Intel Android. Jednym z problemów jest to, że klasa System.Text.RegularExpressions w Dot42 nie ma funkcji Split (), której użyłem w testach Xamarin, więc zamiast tego użyłem klasy Java.Util.Regex i Java.Util.Regex.Pattern.Split () , więc w tym konkretnym miejscu w kodzie istnieje niewielka różnica. Nie powinno to stanowić dużego problemu. Dot42 kompiluje się do kodu Dalvik (DEX), więc natywnie współpracuje z Javą na Androidzie, nie potrzebuje kosztownego współdziałania z C # do Javy jak Xamarin.
Dla porównania uruchamiam również test na urządzeniach ARM - tutaj kod Dot42 jest „tylko” 2x wolniejszy niż Xamarin C #. Oto moje wyniki:
HTC Nexus One Android 2.3.7 (ARM)
Java: Całkowity czas całkowity (5 uruchomień): 12187 ms, z całkowitym odczytem pliku: 13200 ms
Xamarin C #: całkowity czas całkowity (5 uruchomień): 13935 ms, całkowity odczyt pliku: 14465 ms
Dot42 C #: Całkowity czas całkowity (5 uruchomień): 26000 ms, z całkowitym odczytem pliku: 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: Całkowity czas całkowity (5 uruchomień): 6895 ms, całkowity odczyt pliku: 7275 ms
Xamarin C #: całkowity czas całkowity (5 uruchomień): 6466 ms, całkowity odczyt pliku: 6720 ms
Dot42 C #: Całkowity czas całkowity (5 uruchomień): 11185 ms, z całkowitym odczytem pliku: 11843 ms
Emulator Intel, Android 4.2 (x86)
Java: Całkowity czas całkowity (5 uruchomień): 2389 ms, całkowity odczyt pliku: 2770 ms
Xamarin C #: Całkowity czas całkowity (5 uruchomień): 1748 ms, całkowity odczyt pliku: 1933 ms
Dot42 C #: Całkowity czas całkowity (5 uruchomień): 5150 ms, całkowity odczyt pliku: 5459 ms
Dla mnie interesujące było również zauważyć, że Xamarin C # jest nieco szybszy niż Java na nowszym urządzeniu ARM i nieco wolniejszy na starym Nexus One. Jeśli ktoś chciałby również uruchomić te testy, daj mi znać, a zaktualizuję źródła na GitHub. Szczególnie interesujące byłoby zobaczyć wyniki z prawdziwego urządzenia z Androidem z procesorem Intel.
Aktualizacja 26.07.2013
Tylko szybka aktualizacja, ponownie skompilowana przez aplikacje testowe z najnowszą wersją Xamarin.Android 4.8, a także z wydaną dzisiaj aktualizacją dot42 1.0.1.72 - bez istotnych zmian w porównaniu z poprzednimi wynikami.
Aktualizacja 30.07.2013 - lepsze wyniki dla dot42
Ponownie przetestowałem Dot42 z portem Roberta (od twórców dot42) mojego kodu Java do C #. W moim porcie C # wykonanym początkowo dla Xamarin zastąpiłem niektóre rodzime klasy Java, takie jak ListArray, klasą List rodzimą w C # itp. Robert nie miał mojego kodu źródłowego Dot42, więc przeniósł go ponownie z Javy i użył oryginalnych klas Java w takie miejsca, z których korzysta Dot42, tak sądzę, ponieważ działa w Dalvik VM, jak Java, a nie w Mono, jak Xamarin. Teraz wyniki Dot42 są znacznie lepsze. Oto dziennik z moich testów:
30.07.2013 - Testy Dot42 z większą liczbą klas Java w Dot42 C #
Emulator Intel, Android 4.2
Dot42, kod Grega używający StringBuilder.Replace () (jak w Xamarin):
Całkowity czas całkowity (5 uruchomień): 3646 ms, całkowity odczyt pliku: 3830 msDot42, kod Grega za pomocą String.Replace () (jak w Javie i kodzie Roberta):
Całkowity czas całkowity (5 uruchomień): 3027 ms, całkowity odczyt pliku: 3206 msDot42, Kod Roberta:
Całkowity czas całkowity (5 uruchomień): 1781 ms, z całkowitym odczytem pliku: 1999 msXamarin:
całkowity czas całkowity (5 uruchomień): 1373 ms, całkowity odczyt pliku: 1505 msJava:
Całkowity czas całkowity (5 uruchomień): 1841 ms, całkowity odczyt pliku: 2044 msARM, Samsung Galaxy Note 2, wyłączanie oszczędzania energii, Android 4.1.1
Dot42, kod Grega używający StringBuilder.Replace () (jak w Xamarin):
Całkowity czas całkowity (5 uruchomień): 10875 ms, przy całkowitym odczycie pliku: 11280 msDot42, kod Grega za pomocą String.Replace () (jak w Javie i kodzie Roberta):
Całkowity czas całkowity (5 uruchomień): 9710 ms, z całkowitym odczytem pliku: 10097 msDot42, kod Roberta:
Całkowity czas całkowity (5 przebiegów): 6279 ms, całkowity odczyt pliku: 6622 msXamarin:
całkowity czas całkowity (5 uruchomień): 6201 ms, całkowity odczyt pliku: 6476 msJava:
Całkowity czas całkowity (5 uruchomień): 7141 ms, całkowity odczyt pliku: 7479 ms
Nadal uważam, że Dot42 ma przed sobą długą drogę. Posiadanie klas podobnych do Java (np. ArrayList) i dobra wydajność z nimi ułatwiłoby przenoszenie kodu z Java na C #. Jest to jednak coś, czego nie zrobiłbym wiele. Wolałbym użyć istniejącego kodu C # (bibliotek itp.), Który będzie używał natywnych klas C # (np. List), i który działałby wolno z bieżącym kodem dot42 i bardzo dobrze z Xamarin.
Greg
Odpowiedzi:
Tak, wirtualna maszyna Xamarin Mono jest bardziej imponująca niż Dalvik Google'a używany w Androidzie. Przetestowałem to na tabletach HTC Flyer i Acer Iconia Tab, aby przeprowadzić analizę porównawczą portu C # Androida przez Mono w stosunku do Java Dalvik, z dobrą implementacją C # Androida i naprawdę niepokojącą Dalvik opartą na Javie.
źródło
https://medium.com/@harrycheung/mobile-app-performance-redux-e512be94f976#.kfbauchtz
Mam nadzieję, że ta informacja pomoże.
źródło
Niedawno sprawdziliśmy, czy aplikacja Xamarin jest używana. Wykorzystaliśmy kod C #, który już napisaliśmy dla wersji naszej aplikacji Windows RT. Niektóre szczegółowe informacje musiały zostać przepisane dla wersji Androida.
Odkryliśmy, że operacje we / wy w Xamarin C # są około 2x wolniejsze niż Java. Nasza aplikacja jest mocno związana z operacjami we / wy. Nie odkryliśmy jeszcze przyczyny tego, ale w tej chwili zakładamy, że jest to spowodowane zebraniem. Chociaż przez większość czasu staramy się pozostawać wewnątrz maszyny wirtualnej Mono, nie wiemy, w jaki sposób Mono faktycznie uzyskuje dostęp do dysku.
Mówi także, że nasz kod C # używa SQLite.NET ( https://github.com/praeclarum/sqlite-net ). Identyczne pobieranie przy użyciu kodu SQLite.NET jest także 2x wolniejsze niż przy użyciu opakowania Javaite SQLite w Androidzie. Po przejrzeniu kodu źródłowego wydaje się, że wiąże się on bezpośrednio z biblioteką C.dll, więc nie wiem, dlaczego jest o wiele wolniejszy. Jedną z możliwości jest to, że zbieranie ciągów z języka macierzystego na Javę może być szybsze na Androidzie niż rodzime na C # na Xamarinie.
źródło
To kolejny zaktualizowany post na blogu, którym chciałbym się z tobą podzielić . Porównuje Xamarin do natywnego kodu i Cordova zarówno na urządzeniach IO, jak i na Androidzie.
Krótko mówiąc, Xamarin działa czasem lepiej niż kod macierzysty. Przetestował rozmiar aplikacji, czasy ładowania, ładowanie listy z usługi Azure i obliczanie liczb pierwszych.
Cieszyć się!
Edycja: zaktualizowałem martwy link i zauważyłem, że jest część 2
źródło
Oto kilka informacji, które znalazłem w innym teście między rozwiązaniami natywnymi, Xamarin i Xamarin.Forms (testy obejmują również wydajność iOS) na dwóch następujących urządzeniach:
Samsung Galaxy A7 : Wersja systemu Android: 6.0 Jednostka centralna: ośmiordzeniowy 1,9 GHz Cortex-A53 RAM: 3 GB Rozdzielczość wyświetlacza: 1920 × 1080
iPhone 6s : wersja iOS: 10.3.3 Jednostka centralna: dwurdzeniowy 1,84 GHz Twister RAM: 2 GB Rozdzielczość wyświetlacza: 1334 × 750
Porównanie składa się z kilku wspólnych funkcji, każda z własną aplikacją:
Każdy test jest powtarzany kilka razy, wykresy pokazują średnie wyniki.
Witaj świecie
Reszta API
Zestaw testów mających na celu pomiar czasu potrzebnego aplikacji do wysłania żądania za pośrednictwem interfejsu API REST i odebrania odpowiedzi bez dalszego przetwarzania danych przy użyciu interfejsu API OpenWeatherMap.
Testy operacyjne JSON wykonane przy użyciu frameworku Newtonoft Json.net do serializacji i deserializacji obiektów JSON we wszystkich aplikacjach Xamarin. Natywna serializacja i deserializacja Androida została przetestowana przy użyciu dwóch bibliotek Java: Jackson i GSON.
Wykonano dwa przebiegi, pierwszy od zera, drugi z buforowanymi informacjami i operacjami
Pierwszy bieg :
(Natywne operacje JSON na iOS zabijają ten test btw, a Xamarin dołącza do niego w drugim)
Operacje fotograficzne
Najpierw załaduj obrazy w trzech różnych rozdzielczościach:
Coś wydawało się niepewne w wynikach Xamarin.Forms dla tego testu, więc nie jest to uwzględnione na wykresie.
Operacje SQLite
Dwie przetestowane operacje:
Z bazami danych zawierającymi 10 000 rekordów. Wszystkie operacje były przetwarzane wewnętrznie na urządzeniach.
Xamarin Native (Xamarin.iOS / Xamarin.Android) pokazuje się jako raczej dobra alternatywa dla kodu natywnego, podczas gdy Xamarin.Forms wydaje się powolny w wielu przypadkach, ale może być naprawdę dobrym rozwiązaniem do szybkiego tworzenia naprawdę prostych aplikacji.
Pełny test pochodzi z tego źródła:
https://www.altexsoft.com/blog/engineering/performance-comparison-xamarin-forms-xamarin-ios-xamarin-android-vs-android-and-ios-native-applications/
Dziękuję za udzielenie wyjaśnień w celu poprawy mojej odpowiedzi, mam nadzieję, że to trochę pomoże :)
źródło
Wydajność
Wydajność jest niejasnym słowem, jeśli nie zdefiniujesz, co rozumiesz przez wydajność, jeśli jest to zwykła wydajność obliczeniowa Xamarin może być szybszy niż Java, w zależności od charakteru obliczeń.
Android jest standardowo wyposażony w wiele formularzy do wykonywania kodu w:
Jest oczywiste, że podczas wykonywania kodu im bardziej natywne jest rozwiązanie, tym szybciej będzie ono działać. Język oparty na czasie wykonywania nigdy nie przebije języka, który działa bezpośrednio na procesorze.
Ale z drugiej strony, jeśli chcesz zmierzyć rzeczywistą wydajność użytkowania Java jest propbaby będzie szybsza niż Xamarin.
Xamarin i dlaczego może być wolniejszy
Porównując Xamarin ze zwykłymi starymi aplikacjami Java, wydajność może być znacznie wyższa dla Xamarin, ponieważ może być wolniejsza.
W prawdziwym świecie aplikacje Xamarin są prawdopodobnie wolniejsze niż aplikacje Java, ponieważ wiele wywołań systemu Android / Java (systemowych) musi być delegowanych do i z środowiska wykonawczego Xamarin za pomocą tak zwanych powiązań.
Istnieje kilka różnych rodzajów powiązań, o których należy wiedzieć:
Wiązania są bardzo wydajne pod względem wydajności. Wywołanie metody C ++ z Javy powoduje ogromne obciążenie w czasie wywoływania, wywoływanie metody C ++ z poziomu C ++ jest wiele razy szybsze.
Ale nie tylko połączenia JNI są kosztowne, podobnie jak połączenia zi do MCW i ACW. Rzeczywiste aplikacje Xamarin wykonują wiele wywołań za pomocą powiązań, a dzięki temu rzeczywiste użycie aplikacji Xamarin może być (i będzie ogólnie) wolniejsze niż zwykła stara aplikacja Java. Jednak w zależności od sposobu zaprojektowania aplikacji Xamarin jest bardzo prawdopodobne, że użytkownik nawet nie zauważy różnicy.
TLDR / Podsumowanie: Xamarin musi używać powiązań al sort , które są czasochłonne.
źródło
To dość stare testy, ale mogą być istotne: https://github.com/EgorBo/Xamarin.Android-vs-Java
Test arytmetyczny
Kolekcje, generyczne, niestandardowe typy wartości
Praca z ciągami znaków
UPD: nowe dane z Google Pixel 2 (dzięki yousha-aleayoub )
źródło