Mi sono imbattuto in Xamarin affermando che la loro implementazione Mono su Android e le loro app compilate in C # sono più veloci del codice Java. Qualcuno ha eseguito benchmark effettivi su codice Java e C # molto simile su piattaforme Android diverse per verificare tali affermazioni, potrebbe pubblicare il codice e i risultati?
Aggiunto il 18 giugno 2013
Dal momento che non c'era risposta e non è stato possibile trovare tali parametri di riferimento fatti da altri, ho deciso di fare i miei test. Sfortunatamente, la mia domanda rimane "bloccata", quindi non posso pubblicarla come risposta, ma solo modificare la domanda. Si prega di votare per riaprire questa domanda. Per C #, ho usato Xamarin.Android Ver. 4.7.09001 (beta). Il codice sorgente, tutti i dati che ho usato per i test e i pacchetti APK compilati sono su GitHub:
Java: https://github.com/gregko/TtsSetup_Java
C #: https://github.com/gregko/TtsSetup_C_sharp
Se qualcuno volesse ripetere i miei test su altri dispositivi o emulatori, sarei interessato a conoscere anche i risultati.
Risultati dei miei test
Ho portato la mia classe di estrattore di frasi su C # (dalla mia app @Voice Aloud Reader) ed ho eseguito alcuni test su 10 file HTML in inglese, russo, francese, polacco e ceco. Ogni esecuzione è stata eseguita 5 volte su tutti e 10 i file e il tempo totale per 3 diversi dispositivi e un emulatore sono riportati di seguito. Ho testato solo build "Release", senza debug abilitato.
HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM
Java: tempo totale complessivo (5 esecuzioni): 12361 ms, con totale lettura file: 13304 ms
C #: tempo totale complessivo (5 corse): 17504 ms, con totale lettura file: 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: tempo totale complessivo (5 esecuzioni): 8947 ms, con totale lettura file: 9186 ms
C #: tempo totale complessivo (5 corse): 9884 ms, con totale lettura file: 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: tempo totale complessivo (5 esecuzioni): 9742 ms, con totale lettura file: 10111 ms
C #: tempo totale complessivo (5 corse): 10459 ms, con lettura totale del file: 10696 ms
Emulatore - Intel (Android 4.2, API 17)
Java: tempo totale complessivo (5 esecuzioni): 2699 ms, con totale lettura file: 3127 ms
C #: tempo totale complessivo (5 corse): 2049 ms, con lettura totale del file: 2182 ms
Emulatore - Intel (Android 2.3.7, API 10)
Java: tempo totale complessivo (5 esecuzioni): 2992 ms, con totale lettura file: 3591 ms
C #: tempo totale complessivo (5 corse): 2049 ms, con totale lettura file: 2257 ms
Emulatore - Arm (Android 4.0.4, API 15)
Java: tempo totale complessivo (5 esecuzioni): 41751 ms, con totale lettura file: 43866 ms
C #: tempo totale complessivo (5 corse): 44136 ms, con totale lettura file: 45109 ms
Breve discussione
Il mio codice di prova contiene principalmente analisi del testo, sostituzione e ricerche Regex, forse per altri codici (ad es. Più operazioni numeriche) i risultati sarebbero diversi. Su tutti i dispositivi con processori ARM, Java ha funzionato meglio del codice Xamarin C #. La differenza più grande era su Android 2.3, dove il codice C # viene eseguito a ca. 70% della velocità di Java.
Sull'emulatore Intel (con tecnologia Intel HAX, l'emulatore funziona in modalità virt veloce), il codice Xamarin C # esegue il mio codice di esempio molto più velocemente di Java, circa 1,35 volte più veloce. Forse il codice e le librerie della macchina virtuale Mono sono ottimizzati molto meglio su Intel che su ARM?
Modifica 8 luglio 2013
Ho appena installato l'emulatore Android Genymotion, che funziona in Oracle VirtualBox, e di nuovo questo utilizza un processore Intel nativo, non emulando un processore ARM. Come per l'emulatore Intel HAX, anche qui C # funziona molto più velocemente. Ecco i miei risultati:
Emulatore Genymotion - Intel (Android 4.1.1, API 16)
Java: tempo totale complessivo (5 esecuzioni): 2069 ms, con totale lettura file: 2248 ms
C #: tempo totale complessivo (5 corse): 1543 ms, con lettura totale del file: 1642 ms
Ho poi notato che c'era un aggiornamento a Xamarin.Android beta, versione 4.7.11, con note di rilascio che menzionavano anche alcune modifiche nel runtime Mono. Ha deciso di testare rapidamente alcuni dispositivi ARM e una grande sorpresa: i numeri C # sono migliorati:
BN Nook XD +, ARM (Android 4.0)
Java: tempo totale complessivo (5 esecuzioni): 8103 ms, con totale lettura file: 8569 ms
C #: tempo totale complessivo (5 corse): 7951 ms, con totale lettura file: 8161 ms
Wow! C # ora è meglio di Java? Ho deciso di ripetere il test sul mio Galaxy Note 2:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: tempo totale complessivo (5 esecuzioni): 9675 ms, con totale lettura file: 10028 ms
C #: tempo totale complessivo (5 corse): 9911 ms, con lettura totale file: 10104 ms
Qui C # sembra essere solo leggermente più lento, ma questi numeri mi hanno dato una pausa: perché il tempo è più lungo rispetto a Nook HD +, anche se Note 2 ha un processore più veloce? La risposta: modalità di risparmio energetico. In Nook, era disabilitato, in Nota 2 - abilitato. Ha deciso di provare con la modalità di risparmio energetico disabilitata (come abilitata, limita anche la velocità del processore):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), risparmio energetico disabilitato
Java: tempo totale complessivo (5 esecuzioni): 7153 ms, con totale lettura file: 7459 ms
C #: tempo totale complessivo (5 corse): 6906 ms, con totale lettura file: 7070 ms
Ora, sorprendentemente, C # è leggermente più veloce di Java anche sul processore ARM. Grande miglioramento!
Modifica 12 luglio 2013
Sappiamo tutti che nulla batte il codice nativo per la velocità e non ero soddisfatto delle prestazioni del mio divisore di frasi in Java o C #, in particolare che ho bisogno di migliorarlo (e quindi renderlo ancora più lento). Ha deciso di riscriverlo in C ++. Ecco un piccolo (cioè un set di file più piccolo rispetto ai test precedenti, per altri motivi) del confronto tra la velocità nativa e Java sul mio Galaxy Note 2, con la modalità di risparmio energetico disabilitata:
Java: tempo totale complessivo (5 esecuzioni): 3292 ms, con totale lettura file: 3454 ms
Pollice nativo: tempo totale complessivo (5 corse): 537 ms, con lettura totale del file: 657 ms
Braccio nativo: tempo totale complessivo (5 corse): 458 ms, con lettura totale del file: 587 ms
Sembra che per il mio test particolare, il codice nativo sia da 6 a 7 volte più veloce di Java. Avvertenza: impossibile utilizzare la classe std :: regex su Android, quindi ho dovuto scrivere le mie routine specializzate alla ricerca di interruzioni di paragrafo o tag html. I miei test iniziali dello stesso codice su un PC usando regex, erano circa 4-5 volte più veloci di Java.
Accidenti! Risvegliando la memoria grezza con i puntatori char * o wchar *, mi sono sentito subito più giovane di 20 anni! :)
Modifica il 15 luglio 2013
(Vedi di seguito, con modifiche del 30/07/2013, per risultati molto migliori con Dot42)
Con qualche difficoltà, sono riuscito a trasferire i miei test C # su Dot42 (versione 1.0.1.71 beta), un'altra piattaforma C # per Android. I risultati preliminari mostrano che il codice Dot42 è circa 3 volte (3 volte) più lento di Xamarin C # (v. 4.7.11), su un emulatore Intel Android. Un problema è che la classe System.Text.RegularExpressions in Dot42 non ha la funzione Split () che ho usato nei test Xamarin, quindi ho usato invece la classe Java.Util.Regex e Java.Util.Regex.Pattern.Split () , quindi in questo particolare punto del codice c'è questa piccola differenza. Non dovrebbe essere un grosso problema però. Dot42 compila il codice Dalvik (DEX), quindi collabora nativamente con Java su Android, non necessita di interoperazioni costose da C # a Java come Xamarin.
Solo per confronto, eseguo anche il test su dispositivi ARM: qui il codice Dot42 è "solo" 2 volte più lento di Xamarin C #. Ecco i miei risultati:
HTC Nexus One Android 2.3.7 (ARM)
Java: tempo totale complessivo (5 esecuzioni): 12187 ms, con totale lettura file: 13200 ms
Xamarin C #: tempo totale complessivo (5 corse): 13935 ms, con totale lettura file: 14465 ms
Dot42 C #: tempo totale complessivo (5 corse): 26000 ms, con totale lettura file: 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: tempo totale complessivo (5 esecuzioni): 6895 ms, con totale lettura file: 7275 ms
Xamarin C #: tempo totale complessivo (5 corse): 6466 ms, con totale lettura file: 6720 ms
Dot42 C #: tempo totale complessivo (5 corse): 11185 ms, con totale lettura file: 11843 ms
Emulatore Intel, Android 4.2 (x86)
Java: tempo totale complessivo (5 esecuzioni): 2389 ms, con lettura totale del file: 2770 ms
Xamarin C #: tempo totale complessivo (5 corse): 1748 ms, con totale lettura file: 1933 ms
Dot42 C #: tempo totale complessivo (5 corse): 5150 ms, con lettura totale del file: 5459 ms
Per me, è stato anche interessante notare che Xamarin C # è leggermente più veloce di Java su un nuovo dispositivo ARM e leggermente più lento sul vecchio Nexus One. Se qualcuno desidera eseguire anche questi test, per favore fatemelo sapere e aggiornerò i sorgenti su GitHub. Sarebbe particolarmente interessante vedere i risultati da un vero dispositivo Android con processore Intel.
Aggiornamento 26/07/2013
Solo un aggiornamento rapido, ricompilato dalle app di riferimento con l'ultimo Xamarin.Android 4.8 e anche con l'aggiornamento dot42 1.0.1.72 rilasciato oggi - nessuna modifica significativa rispetto ai risultati precedentemente riportati.
Aggiornamento del 30/07/2013 - risultati migliori per dot42
Testato nuovamente Dot42 con la porta di Robert (dai produttori di dot42) del mio codice Java su C #. Nella mia porta C # fatta inizialmente per Xamarin, ho sostituito alcune classi Java native, come ListArray, con la classe List nativa di C #, ecc. Robert non aveva il mio codice sorgente Dot42, quindi lo portò di nuovo da Java e usò le classi Java originali in tali luoghi, che avvantaggia Dot42, immagino perché funziona in Dalvik VM, come Java, e non in Mono, come Xamarin. Ora i risultati di Dot42 sono molto migliori. Ecco un registro dai miei test:
30/07/2013 - Test Dot42 con più classi Java in Dot42 C #
Emulatore Intel, Android 4.2
Dot42, Codice di Greg che utilizza StringBuilder.Replace () (come in Xamarin):
tempo totale complessivo (5 corse): 3646 ms, con lettura totale del file: 3830 msDot42, Codice di Greg che utilizza String.Replace () (come in Java e il codice di Robert):
tempo totale complessivo (5 esecuzioni): 3027 ms, con lettura totale del file: 3206 msDot42, Codice Robert:
tempo totale complessivo (5 corse): 1781 ms, con lettura totale file: 1999 msXamarin:
tempo totale complessivo (5 corse): 1373 ms, con totale lettura file: 1505 msJava:
tempo totale complessivo (5 esecuzioni): 1841 ms, con totale lettura file: 2044 msARM, Samsung Galaxy Note 2, risparmio energetico, Android 4.1.1
Dot42, Codice di Greg che utilizza StringBuilder.Replace () (come in Xamarin):
tempo totale complessivo (5 corse): 10875 ms, con lettura totale del file: 11280 msDot42, Codice di Greg che utilizza String.Replace () (come in Java e il codice di Robert):
tempo totale complessivo (5 esecuzioni): 9710 ms, con lettura totale del file: 10097 msDot42, Codice Robert:
tempo totale complessivo (5 corse): 6279 ms, con lettura totale file: 6622 msXamarin:
tempo totale complessivo (5 corse): 6201 ms, con totale lettura file: 6476 msJava:
tempo totale complessivo (5 esecuzioni): 7141 ms, con totale lettura file: 7479 ms
Penso ancora che Dot42 abbia ancora molta strada da fare. Avere classi simili a Java (ad es. ArrayList) e una buona prestazione con esse renderebbe il porting del codice da Java a C # leggermente più semplice. Tuttavia, questo è qualcosa che non avrei molte probabilità di fare molto. Preferirei usare il codice C # esistente (librerie, ecc.), Che utilizzerà le classi C # native (ad es. Elenco) e che funzionerebbe lentamente con l'attuale codice dot42 e molto bene con Xamarin.
Greg