Me deparei com o Xamarin afirma que sua implementação Mono no Android e seus aplicativos compilados em C # são mais rápidos que o código Java. Alguém executou benchmarks reais em códigos Java e C # muito semelhantes em diferentes plataformas Android para verificar essas alegações, poderia postar o código e os resultados?
Adicionado 18 de junho de 2013
Como não houve resposta e não consegui encontrar esses benchmarks feitos por outros, decidi fazer meus próprios testes. Infelizmente, minha pergunta permanece "bloqueada", portanto não posso postar isso como resposta, apenas edite a pergunta. Por favor vote para reabrir esta pergunta. Para C #, usei o Xamarin.Android Ver. 4.7.09001 (beta). O código fonte, todos os dados que usei para testar e compilar pacotes APK estão no GitHub:
Java: https://github.com/gregko/TtsSetup_Java
C #: https://github.com/gregko/TtsSetup_C_sharp
Se alguém quiser repetir meus testes em outros dispositivos ou emuladores, também ficaria interessado em saber os resultados.
Resultados dos meus testes
Portei minha classe extrator de frases para C # (do meu aplicativo @Voice Aloud Reader) e executei alguns testes em 10 arquivos HTML nos idiomas inglês, russo, francês, polonês e tcheco. Cada execução foi realizada 5 vezes em todos os 10 arquivos, e o tempo total para 3 dispositivos diferentes e um emulador é publicado abaixo. Testei compilações "Release" apenas, sem a depuração ativada.
HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM
Java: tempo total geral (5 execuções): 12361 ms, com leitura total de arquivos: 13304 ms
C #: tempo total geral (5 execuções): 17504 ms, com leitura total de arquivos: 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: tempo total geral (5 execuções): 8947 ms, com total de leitura de arquivos: 9186 ms
C #: tempo total geral (5 execuções): 9884 ms, com leitura total de arquivos: 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: tempo total geral (5 execuções): 9742 ms, com total de leitura de arquivos: 10111 ms
C #: tempo total geral (5 execuções): 10459 ms, com leitura total de arquivos: 10696 ms
Emulador - Intel (Android 4.2, API 17)
Java: tempo total geral (5 execuções): 2699 ms, com leitura total de arquivos: 3127 ms
C #: tempo total geral (5 execuções): 2049 ms, com leitura total de arquivos: 2182 ms
Emulador - Intel (Android 2.3.7, API 10)
Java: tempo total geral (5 execuções): 2992 ms, com total de leitura de arquivo: 3591 ms
C #: tempo total geral (5 execuções): 2049 ms, com leitura total de arquivos: 2257 ms
Emulador - Braço (Android 4.0.4, API 15)
Java: tempo total geral (5 execuções): 41751 ms, com leitura total de arquivos: 43866 ms
C #: tempo total geral (5 execuções): 44136 ms, com leitura total de arquivos: 45109 ms
Breve discussão
Meu código de teste contém principalmente análise de texto, substituição e pesquisas de Regex, talvez para outro código (por exemplo, operações numéricas) os resultados sejam diferentes. Em todos os dispositivos com processadores ARM, o Java teve um desempenho melhor que o código Xamarin C #. A maior diferença ocorreu no Android 2.3, onde o código C # é executado em aprox. 70% da velocidade do Java.
No emulador Intel (com a tecnologia Intel HAX, o emulador é executado no modo virt rápido), o código Xamarin C # executa meu código de amostra muito mais rápido que Java - cerca de 1,35 vezes mais rápido. Talvez o código da máquina virtual Mono e as bibliotecas sejam muito mais otimizadas na Intel do que no ARM?
Editar 8 de julho de 2013
Acabei de instalar o emulador Genymotion Android, que é executado no Oracle VirtualBox, e novamente este usa processador Intel nativo, não emulando o processador ARM. Como no emulador Intel HAX, novamente o C # roda aqui muito mais rápido. Aqui estão meus resultados:
Emulador Genymotion - Intel (Android 4.1.1, API 16)
Java: tempo total geral (5 execuções): 2069 ms, com total de leitura de arquivo: 2248 ms
C #: tempo total geral (5 execuções): 1543 ms, com total de leitura de arquivos: 1642 ms
Percebi então que havia uma atualização para o Xamarin.Android beta, versão 4.7.11, com notas de versão mencionando também algumas mudanças no tempo de execução do Mono. Decidiu testar rapidamente alguns dispositivos ARM e grande surpresa - os números de C # melhoraram:
BN Nook XD +, ARM (Android 4.0)
Java: tempo total geral (5 execuções): 8103 ms, com total de leitura de arquivos: 8569 ms
C #: tempo total geral (5 execuções): 7951 ms, com total de leitura de arquivos: 8161 ms
Uau! C # agora é melhor que Java? Decidi repetir o teste no meu Galaxy Note 2:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: tempo total geral (5 execuções): 9675 ms, com total de leitura de arquivo: 10028 ms
C #: tempo total geral (5 execuções): 9911 ms, com total de leitura de arquivos: 10104 ms
Aqui, o C # parece ser apenas um pouco mais lento, mas esses números me deram uma pausa: por que o tempo é maior do que no Nook HD +, mesmo que a Nota 2 tenha um processador mais rápido? A resposta: modo de economia de energia. No Nook, foi desativado, na Nota 2 - ativada. Decidiu testar com o modo de economia de energia desativado (como ativado, também limita a velocidade do processador):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), economia de energia desativada
Java: tempo total geral (5 execuções): 7153 ms, com total de leitura de arquivos: 7459 ms
C #: tempo total geral (5 execuções): 6906 ms, com total de leitura de arquivos: 7070 ms
Agora, surpreendentemente, o C # também é um pouco mais rápido que o Java no processador ARM. Grande melhoria!
Editar 12 de julho de 2013
Todos sabemos que nada supera o código nativo por velocidade, e não fiquei satisfeito com o desempenho do meu divisor de frases em Java ou C #, principalmente porque preciso melhorá-lo (e, assim, torná-lo ainda mais lento). Decidiu reescrevê-lo em C ++. Aqui está uma pequena comparação (ou seja, um conjunto menor de arquivos que os testes anteriores, por outras razões) da velocidade do nativo vs. Java no meu Galaxy Note 2, com o modo de economia de energia desativado:
Java: tempo total geral (5 execuções): 3292 ms, com leitura total de arquivos: 3454 ms
Thumb nativo: tempo total geral (5 execuções): 537 ms, com total de leitura de arquivos: 657 ms
Braço nativo: tempo total geral (5 execuções): 458 ms, com leitura total de arquivos: 587 ms
Parece que, para o meu teste específico, o código nativo é 6 a 7 vezes mais rápido que o Java. Advertência: não era possível usar a classe std :: regex no Android; portanto, tive que escrever minhas próprias rotinas especializadas em busca de quebras de parágrafos ou tags html. Meus testes iniciais do mesmo código em um PC usando regex foram cerca de 4 a 5 vezes mais rápidos que o Java.
Ufa! Ao despertar a memória bruta com ponteiros char * ou wchar * novamente, senti-me instantaneamente 20 anos mais novo! :)
Editar 15 de julho de 2013
(Veja abaixo, com edições de 30/07/2013, para obter resultados muito melhores com o Dot42)
Com alguma dificuldade, consegui portar meus testes de C # para o Dot42 (versão 1.0.1.71 beta), outra plataforma de C # para Android. Resultados preliminares mostram que o código Dot42 é cerca de 3x (3 vezes) mais lento que o Xamarin C # (v. 4.7.11), em um emulador Intel Android. Um problema é que a classe System.Text.RegularExpressions no Dot42 não possui a função Split () usada nos testes do Xamarin, então usei a classe Java.Util.Regex e Java.Util.Regex.Pattern.Split () , portanto, neste local específico no código, há essa pequena diferença. Não deve ser um grande problema. O Dot42 é compilado no código Dalvik (DEX), portanto, ele coopera com o Java no Android nativamente, não precisa de interoperabilidade cara do C # para o Java, como o Xamarin.
Apenas para comparação, também executei o teste em dispositivos ARM - aqui o código Dot42 é "apenas" 2x mais lento que o Xamarin C #. Aqui estão meus resultados:
HTC Nexus One Android 2.3.7 (ARM)
Java: tempo total geral (5 execuções): 12187 ms, com leitura total de arquivos: 13200 ms
Xamarin C #: tempo total geral (5 execuções): 13935 ms, com total de leitura de arquivos: 14465 ms
Dot42 C #: tempo total geral (5 execuções): 26000 ms, com total de leitura de arquivos: 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: tempo total geral (5 execuções): 6895 ms, com total de leitura de arquivo: 7275 ms
Xamarin C #: tempo total geral (5 execuções): 6466 ms, com total de leitura de arquivos: 6720 ms
Dot42 C #: tempo total geral (5 execuções): 11185 ms, com leitura total de arquivos: 11843 ms
Emulador Intel, Android 4.2 (x86)
Java: tempo total geral (5 execuções): 2389 ms, com total de leitura de arquivos: 2770 ms
Xamarin C #: tempo total geral (5 execuções): 1748 ms, com total de leitura de arquivos: 1933 ms
Dot42 C #: tempo total geral (5 execuções): 5150 ms, com total de leitura de arquivos: 5459 ms
Para mim, também foi interessante observar que o Xamarin C # é um pouco mais rápido que o Java em um dispositivo ARM mais novo e um pouco mais lento no antigo Nexus One. Se alguém quiser executar esses testes também, informe-me e atualizarei as fontes no GitHub. Seria particularmente interessante ver resultados de um dispositivo Android real com processador Intel.
Atualização 26/07/2013
Apenas uma atualização rápida, recompilada por aplicativos de benchmark com o Xamarin.Android 4.8 mais recente e também com a atualização do dot42 1.0.1.72 lançada hoje - sem alterações significativas em relação aos resultados relatados anteriormente.
Atualização 30/07/2013 - melhores resultados para dot42
Re-testei o Dot42 com a porta de Robert (do ponto42 fabricantes) do meu código Java para C #. Na minha porta C # feita inicialmente para o Xamarin, substituí algumas classes Java nativas, como ListArray, pela classe List nativa para C # etc. nesses lugares, o que beneficia o Dot42, eu acho, porque roda em Dalvik VM, como Java, e não em Mono, como Xamarin. Agora, os resultados do Dot42 são muito melhores. Aqui está um log do meu teste:
30/07/2013 - Dot42 testa com mais classes Java no Dot42 C #
Emulador Intel, Android 4.2
Dot42, o código de Greg usando StringBuilder.Replace () (como no Xamarin):
tempo total geral (5 execuções): 3646 ms, com total de leitura de arquivo: 3830 msDot42, o código de Greg usando String.Replace () (como no código de Java e Robert):
tempo total geral (5 execuções): 3027 ms, com leitura total de arquivos: 3206 msDot42, código de Robert:
tempo total geral (5 execuções): 1781 ms, com leitura total de arquivos: 1999 msXamarin:
Tempo total geral (5 execuções): 1373 ms, com leitura total de arquivos: 1505 msJava:
tempo total geral (5 execuções): 1841 ms, com leitura total de arquivos: 2044 msARM, Samsung Galaxy Note 2, economia de energia, Android 4.1.1
Dot42, o código de Greg usando StringBuilder.Replace () (como no Xamarin):
tempo total geral (5 execuções): 10875 ms, com total de leitura de arquivo: 11280 msDot42, o código de Greg usando String.Replace () (como no código de Java e Robert):
tempo total geral (5 execuções): 9710 ms, com total de leitura de arquivo: 10097 msDot42, código de Robert:
tempo total geral (5 execuções): 6279 ms, com total de leitura de arquivos: 6622 msXamarin:
tempo total geral (5 execuções): 6201 ms, com total de leitura de arquivos: 6476 msJava:
tempo total geral (5 execuções): 7141 ms, com leitura total de arquivos: 7479 ms
Eu ainda acho que o Dot42 ainda tem um longo caminho a percorrer. Ter classes semelhantes a Java (por exemplo, ArrayList) e um bom desempenho com elas tornaria a portabilidade de código de Java para C # um pouco mais fácil. No entanto, isso é algo que provavelmente não faria muito. Eu preferiria usar o código C # existente (bibliotecas etc.), que usará classes C # nativas (por exemplo, Lista), e que executariam lentamente com o código dot42 atual e muito bem com o Xamarin.
Greg