Alguém tem referências (código e resultados) comparando o desempenho de aplicativos Android escritos em Xamarin C # e Java? [fechadas]

544

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 ms

Dot42, 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 ms

Dot42, código de Robert:
tempo total geral (5 execuções): 1781 ms, com leitura total de arquivos: 1999 ms

Xamarin:
Tempo total geral (5 execuções): 1373 ms, com leitura total de arquivos: 1505 ms

Java:
tempo total geral (5 execuções): 1841 ms, com leitura total de arquivos: 2044 ms

ARM, 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 ms

Dot42, 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 ms

Dot42, código de Robert:
tempo total geral (5 execuções): 6279 ms, com total de leitura de arquivos: 6622 ms

Xamarin:
tempo total geral (5 execuções): 6201 ms, com total de leitura de arquivos: 6476 ms

Java:
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

gregko
fonte
5
Modo DEBUG no Nexus 7 4.2.2 com algumas otimizações em strings e xamarin alpha 9: Tempo total: 3907 ms, com leitura total de arquivos: 4016. O que significa "5 execuções"?
Softlion
1
"esta pergunta provavelmente solicitará debate, argumentos, pesquisas ou discussão prolongada" <- veja acima;)
LearnCocos2D
2
@ LearnCocos2D - Estou apenas reportando resultados e números concretos, isto é, fatos. Senhores não contestam fatos :)
gregko
2
bem, os cientistas fazem;) há uma diferença entre comportamento e fato observado. Há muito mais para se tornar fato, e mesmo assim a aplicabilidade a outros usuários / situações permanece questionável. Esse é o cerne dos benchmarks, eles apenas apresentam fatos à superfície - até você descobrir que o fornecedor x otimizou seu driver para um aplicativo de benchmark específico. Em uma nota relacionada, uma vez foi comprovado que a água tem memória (ou seja, o teste da homeopatia), que foi refutado após o viés do examinador ser considerado e descartado, e não mostrou qualquer significância estatística.
LearnCocos2D
3
além disso, com a próxima versão +0.1, essas características de desempenho podem mudar significativamente - é quando todos os seus esforços apresentados aqui mudam de "fato" para "discutível". No entanto, quem vem aqui pode perceber isso como um fato e tirar a conclusão errada. Outro ponto crucial dos benchmarks: eles são apenas representativos para um dado momento e versões do software utilizado. No dia seguinte, eles podem não refletir mais a realidade. Você deve continuar testando novamente os resultados. É por isso que os resultados aqui podem ser considerados subjetivos e com pouco ou nenhum significado.
LearnCocos2D

Respostas:

62

Sim, a máquina virtual Mono da Xamarin é mais impressionante do que o Dalvik do Google usado no Android. Testei-o com os tablets HTC Flyer e Acer Iconia Tab para comparar a porta C # do Android através do Mono contra o Java Dalvik, com a implementação C # do Android bem e superando verdadeiramente o Dalvik baseado em Java.

klvtsov
fonte
4
@ PeterLawrey, consulte a minha atualização da pergunta. Pretendo portar parte do código Java da minha vida real para C # e executar benchmarks, depois publicá-los aqui - se eles reabrirem minha pergunta, pois os vigilantes do SO o fecharam quase imediatamente.
gregko
1
@ PeterLawrey - Eu agora conduzi meus testes e publiquei resultados no StackOverflow, mas dentro da própria pergunta, pois ela ainda permanece "bloqueada" e não pode postar uma resposta. Se puder, adicione seu voto para reabrir a pergunta. Os resultados são interessantes, no ARM Java vence sem esforço, no Intel - o código C # no Mono é muito mais rápido.
Gregko
9
@gregko Vale a pena notar que você vê o C # sendo emulado mais rapidamente, mas o Java é mais rápido em telefones reais. Para mim, essa é uma distinção importante. Eu não me preocuparia com o desempenho do emulador, na verdade eu sugeriria que você desejasse que o emulador fosse tão lento / rápido quanto o real. Eu votei para reabrir.
Peter Lawrey
14
Tenha cuidado ao usar expressões regulares como um teste de desempenho. Diferenças algorítmicas na implementação de ER podem fazer grandes diferenças. O que você pode estar testando acima é a qualidade de implementação do ER, não as VMs Dalvik ou Mono. Um teste melhor seria o código de análise escrito à mão que usa algoritmos idênticos e óbvios, escritos em um estilo idiomático para cada idioma.
5608 Christopher
4
Esta resposta é inútil sem nenhuma explicação sobre como você executou esses testes ou resultados. Como é agora: completamente baseado em opiniões.
Rolfツ
34

Recentemente, investigamos o uso do Xamarin para um aplicativo. Utilizamos o código C # que já havia escrito para a versão Windows RT do nosso aplicativo. Alguns detalhes específicos tiveram que ser reescritos para a versão Android.

O que descobrimos é que a E / S no Xamarin C # é aproximadamente duas vezes mais lenta que o Java. Nosso aplicativo é fortemente vinculado a E / S. Ainda não descobrimos a causa disso, mas, no momento, estamos assumindo que é devido ao empacotamento. Embora tentemos permanecer na VM Mono a maior parte do tempo, não sabemos como o Mono realmente acessa o disco.

Também está dizendo que nosso código C # usa SQLite.NET ( https://github.com/praeclarum/sqlite-net ). Buscas idênticas usando o código SQLite.NET também são duas vezes mais lentas do que o wrapper Java SQLite do Android. Depois de analisar o código-fonte, ele parece vincular-se diretamente ao C .dll, então não sei por que é muito mais lento. Uma possibilidade é que o empacotamento de strings do nativo para o Java seja mais rápido no Android do que o nativo do C # no Xamarin.

Christopher
fonte
1
Provavelmente, isso também ocorre devido às "ligações" que o Xamerin precisa interagir com o sistema. Cada chamada do sistema, por padrão, vai para uma classe Java, mas precisa ser delegada à Mono VM, o que leva tempo. O mesmo também acontece ao contrário. Eu expliquei isso um pouco mais na minha resposta: stackoverflow.com/a/46973819/1052697
Rolf #:
33

Este é outro post de blog mais atualizado que gostaria de compartilhar com você . Ele compara o Xamarin ao código nativo e ao Cordova nos IOs e no Android.

Em poucas palavras, o Xamarin às vezes tem um desempenho melhor que o código nativo. Ele testou o tamanho do aplicativo, os tempos de carregamento, carregando uma lista do serviço do Azure e o cálculo dos números primos.

Aproveitar!

Edit: Eu atualizei o link morto e notei que há uma parte 2

Daniel
fonte
11

Aqui estão algumas informações que encontrei em outro teste entre soluções nativas, Xamarin e Xamarin.Forms (os testes também incluem performances do iOS) nos dois dispositivos a seguir:

Samsung Galaxy A7 : versão do sistema operacional Android: 6.0 Unidade de processamento central: Octa-core 1.9 GHz Cortex-A53 RAM: 3GB Resolução da tela: 1920 × 1080

iPhone 6s : versão iOS: 10.3.3 Unidade de processamento central: Dual-core 1,84 GHz Twister RAM: 2 GB Resolução da tela: 1334 × 750

A comparação é feita em alguns recursos comuns, cada um com sua própria aplicação:

- Basic Hello World
- REST API
- JSON Serialization/Deserialization
- Photo Loading
- SQL Database Insert and Get All

Cada teste é repetido várias vezes, os gráficos mostram os resultados médios.


Olá Mundo

Comparação básica de desempenho mundial Hellow


API Rest

Conjunto de testes destinados a medir o tempo que leva para o aplicativo enviar uma solicitação por meio da API REST e receber a resposta de volta sem processamento adicional de dados, usando a API OpenWeatherMap.

Comparação de desempenho da API de descanso


Testes de operações JSON feitos usando a estrutura Newtonsoft Json.net para serializar e desserializar objetos JSON em todos os aplicativos Xamarin. Serialização e desserialização nativas do Android testadas usando duas bibliotecas Java: Jackson e GSON.

São feitas duas execuções, uma primeira do zero e outra com informações e operações em cache

Primeira corrida :

Primeira execução de serialização JSON

Desserialização JSON primeira execução

(Operações JSON nativas do iOS estão acabando com esse teste, e o Xamarin se junta a ele no segundo)

Segunda execução de serialização JSON

Segunda execução de desserialização JSON


Operações fotográficas

Primeiro carregamento de imagens com três resoluções diferentes:

Resolution  858×569, Size  868Kb
Resolution  2575×1709, Size  8Mb
Resolution  4291×2848, Size  28.9Mb

Imagem Android primeiro carregamento

Primeiro carregamento da imagem iOS

Algo parecia inseguro sobre os resultados do Xamarin.Forms para este teste, portanto ele não está incluído no gráfico.


Operações SQLite

Duas operações testadas:

BulkInsert: Loading rows of data into a database table.
GetAll: Retrieving all data from the database.

Com bancos de dados com 10.000 registros. Todas as operações foram processadas internamente nos dispositivos.

Desempenho do SQLite para Android

Desempenho do SQLite iOS


O Xamarin Native (Xamarin.iOS / Xamarin.Android) mostra-se como boas alternativas ao código nativo, enquanto o Xamarin.Forms parece lento em muitos casos, mas pode ser uma solução muito boa para desenvolver aplicativos realmente simples rapidamente.

O teste completo vem desta fonte:

https://www.altexsoft.com/blog/engineering/performance-comparison-xamarin-forms-xamarin-ios-xamarin-android-vs-android-and-ios-native-applications/

Obrigado por me dar as explicações para melhorar minha resposta, espero que ajude um pouco :)

Burgito
fonte
7

atuação

Desempenho é uma palavra vaga, se você não definir o que quer dizer com desempenho, se é desempenho claro da computação, o Xamarin pode ser mais rápido que Java, dependendo da natureza da computação.

O Android vem nativamente com formulários multipe para executar código em:

  • RenderScript (CPU e GPU)
  • Java (SDK)
  • C ++ (NDK)
  • OpenGL (GPU)

É bastante óbvio que, ao executar o código, quanto mais nativa a solução, mais rápida ela será. Um idioma baseado em tempo de execução nunca supera um idioma que é executado diretamente na CPU.

Mas, por outro lado, se você deseja medir o desempenho do uso na vida real, o Java provavelmente será mais rápido que o Xamarin.

Xamarin e por que pode ser mais lento

Ao comparar o Xamarin com aplicativos Java antigos simples, o desempenho pode muito bem ser mais rápido para o Xamarin, pois pode ser mais lento.

Em um exemplo do mundo real, é muito provável que os aplicativos Xamarin sejam mais lentos que os aplicativos Java, porque muitas chamadas Android / Java (sistema) precisam ser delegadas para e a partir do tempo de execução do Xamarin usando as chamadas ligações.

Existem alguns tipos diferentes de ligações que são importantes saber:

  • JNI (Java Native Interface): a ligação usada em muitos aplicativos Android para fazer a interface entre o código Java (SDK) e o código C ++ nativo (NDK).
  • MCW (Managed Callable Wrappers): uma ligação disponível no Xamarin para fazer a interface entre o código C # gerenciado e o código Java (tempo de execução do Android).
  • ACW (Android Callable Wrappers): uma ligação disponível no Xamarin para fazer a interface do código Java (tempo de execução do Android) para o código C # gerenciado.

Mais sobre MCW e ACW aqui: https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_1_-_understanding_the_xamarin_mobile_platform/

As ligações são em termos de desempenho muito, muito caras. Invocar um método C ++ do Java adiciona uma enorme sobrecarga no tempo de chamada, chamar um método C ++ de dentro do C ++ é muitas e muitas vezes mais rápido.

Alguém fez um teste de desempenho para calcular quantas operações Java, em média, uma chamada JNI custa: Qual é a sobrecarga quantitativa de fazer uma chamada JNI?

Mas não apenas as chamadas JNI são caras, como também as chamadas de e para MCW e ACW. Os aplicativos Xamarin do mundo real fazem muitas chamadas usando ligações e, devido a esse mundo real, o uso de um aplicativo Xamarin pode ser (e geralmente será) mais lento que um aplicativo Java simples e antigo. No entanto, dependendo de como o aplicativo Xamarin foi projetado, é muito provável que o usuário nem perceba a diferença.

TLDR / Conclusão: O Xamarin precisa usar todos os tipos de ligações, que são caras em termos de tempo.

Além das ligações, existem muitos outros fatores envolvidos ao falar sobre o desempenho no mundo real, por exemplo: tamanho do binário, carregamento do aplicativo na memória, operações de E / S e muito mais. Uma postagem no blog que investiga algumas dessas coisas pode ser encontrada aqui: https://magenic.com/thinking/mobile-development-platform-performance-part-2-native-cordova-classic-xamarin-xamarin-forms

Rolf ツ
fonte