有没有人比较用Xamarin C#和Java编写的Android应用程序的性能基准(代码和结果)?

gre*_*gko 536 c# java android xamarin dot42

我遇到Xamarin声称他们在Android上的Mono实现和他们的C#编译应用程序比Java代码更快.有没有人对不同Android平台上非常相似的Java和C#代码执行实际基准来验证此类声明,是否可以发布代码和结果?

2013年6月18日新增

由于没有答案,也找不到其他人做的基准,所以决定自己做测试.不幸的是,我的问题仍然是"锁定",所以我不能将其作为答案发布,只编辑问题.请投票重新打开这个问题.对于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文件进行了一些测试.所有10个文件的每次运行都执行了5次,下面发布了3个不同设备和一个模拟器的总时间.我只测试了"Release"版本,没有启用调试.

HTC Nexus One Android 2.3.7(API 10) - CyanogenMod ROM

Java:总计时间(5次运行):12361 ms,文件读取总计:13304 ms

C#:总计时间(5次运行):17504 ms,文件读取总计:17956 ms

三星Galaxy S2 SGH-I777(Android 4.0.4,API 15) - CyanogenMod ROM

Java:总计时间(5次运行):8947 ms,文件读取总计:9186 ms

C#:总计时间(5次运行):9884 ms,文件读取总计:10247 ms

三星GT-N7100(Android 4.1.1 JellyBean,API 16) - 三星ROM

Java:总计时间(5次运行):9742 ms,文件读取总计:10111 ms

C#:总计时间(5次运行):10459 ms,文件读取总计:10696 ms

仿真器 - 英特尔(Android 4.2,API 17)

Java:总时间(5次运行):2699 ms,文件读取总数:3127 ms

C#:总计时间(5次运行):2049 ms,文件读数总计:2182 ms

仿真器 - 英特尔(Android 2.3.7,API 10)

Java:总计时间(5次运行):2992 ms,文件读取总计:3591 ms

C#:总计时间(5次运行):2049 ms,文件读取总数:2257 ms

模拟器 - 手臂(Android 4.0.4,API 15)

Java:总计时间(5次运行):41751 ms,文件读取总计:43866 ms

C#:总计时间(5次运行):44136 ms,文件读取总计:45109 ms

简要讨论

我的测试代码主要包含文本解析,替换和正则表达式搜索,可能用于其他代码(例如更多的数字操作),结果会有所不同.在所有使用ARM处理器的设备上,Java的性能优于Xamarin C#代码.最大的区别在于Android 2.3,其中C#代码大约运行.70%的Java速度.

在英特尔模拟器上(使用英特尔HAX技术,模拟器以快速模式运行),Xamarin C#代码比Java快得多地运行我的示例代码 - 大约快了1.35倍.也许Mono虚拟机代码和库在英特尔上比在ARM上更优化?

编辑2013年7月8日

我刚刚安装了在Oracle VirtualBox中运行的Genymotion Android模拟器,而且这个模拟器再次使用原生英特尔处理器,而不是模拟ARM处理器.与英特尔HAX仿真器一样,C#再次在这里运行得更快.这是我的结果:

Genymotion模拟器 - 英特尔(Android 4.1.1,API 16)

Java:总计时间(5次运行):2069 ms,文件读取总计:2248 ms

C#:总计时间(5次运行):1543 ms,文件读取总计:1642 ms

然后我注意到Xamarin.Android beta版本4.7.11有更新,发行说明也提到了Mono运行时的一些变化.决定快速测试一些ARM设备,并且大惊喜--C#数字得到改善:

BN Nook XD +,ARM(Android 4.0)

Java:总计时间(5次运行):8103 ms,文件读取总计:8569 ms

C#:总计时间(5次运行):7951 ms,文件读取总计:8161 ms

哇!C#现在比Java好吗?决定在我的Galaxy Note 2上重复测试:

三星Galaxy Note 2 - ARM(Android 4.1.1)

Java:总计时间(5次运行):9675 ms,文件读取总计:10028 ms

C#:总计时间(5次运行):9911 ms,文件读取总计:10104 ms

这里的C#似乎只是稍微慢一点,但这些数字给了我一个停顿:为什么时间比Nook HD +更长,即使Note 2有更快的处理器?答案:省电模式.在Nook上,它已被禁用,在注2 - 已启用.决定禁用省电模式进行测试(与启用时一样,它也会限制处理器速度):

三星Galaxy Note 2 - ARM(Android 4.1.1),省电禁用

Java:总计时间(5次运行):7153 ms,文件读取总计:7459 ms

C#:总计时间(5次运行):6906 ms,文件读取总计:7070 ms

现在,令人惊讶的是,C#在ARM处理器上的速度也略快于Java.大改进!

编辑2013年7月12日

我们都知道,没有什么比速度本机代码更好,我对Java或C#中的句子分割器的性能不满意,特别是我需要改进它(从而使它更慢).决定用C++重写它.这是一个小的(即比以前的测试更小的文件集,出于其他原因)比较我的Galaxy Note 2上原生与Java的速度,禁用了省电模式:

Java:总计时间(5次运行):3292 ms,文件读取总计:3454 ms

Native thumb:总计总时间(5次运行):537 ms,文件读取总计:657 ms

本机臂:总计时间(5次运行):458 ms,文件读数总计:587 ms

看起来对于我的特定测试,本机代码比Java快6到7倍.警告:无法在Android上使用std :: regex类,因此必须编写我自己的专用例程来搜索段落符号或html标记.我在使用正则表达式的PC上对相同代码的初始测试比Java快4到5倍.

唷!再次使用char*或wchar*指针唤醒原始内存,我立即觉得年轻20岁!:)

编辑2013年7月15日

(请参见下文,编辑时间为2013年7月30日,以获得更好的Dot42结果)

有一些困难,我设法将我的C#测试移植到Dot42(版本1.0.1.71 beta),另一个用于Android的C#平台.初步结果显示,在Intel Android仿真器上,Dot42代码比Xamarin C#(v.4.7.11)慢约3倍(3倍).一个问题是Dot42中的System.Text.RegularExpressions类没有我在Xamarin测试中使用的Split()函数,所以我使用了Java.Util.Regex类,而Java.Util.Regex.Pattern.Split() ,所以在代码中的这个特定位置,存在这种小差异.不过应该不是一个大问题.Dot42编译为Dalvik(DEX)代码,因此它本身就与Android上的Java合作,不需要像Xamarin那样从C#到Java的昂贵的互操作.

仅仅为了比较,我还在ARM设备上运行测试 - 这里的Dot42代码"仅"比Xamarin C#慢2倍.这是我的结果:

HTC Nexus One Android 2.3.7(ARM)

Java:总计时间(5次运行):12187 ms,文件读取总计:13200 ms

Xamarin C#:总计时间(5次运行):13935 ms,文件读取总数:14465 ms

Dot42 C#:总计时间(5次运行):26000 ms,文件读取总计:27168 ms

三星Galaxy Note 2,Android 4.1.1(ARM)

Java:总计时间(5次运行):6895 ms,文件读取总数:7275 ms

Xamarin C#:总计时间(5次运行):6466 ms,文件读取总计:6720 ms

Dot42 C#:总计时间(5次运行):11185 ms,文件读取总数:11843 ms

英特尔模拟器,Android 4.2(x86)

Java:总计时间(5次运行):2389 ms,文件读取总计:2770 ms

Xamarin C#:总计时间(5次运行):1748 ms,文件读取总数:1933 ms

Dot42 C#:总计时间(5次运行):5150 ms,文件读取总数:5459 ms

对我来说,值得注意的是,Xamarin C#在较新的ARM设备上略快于Java,在旧的Nexus One上略慢.如果有人想要运行这些测试,请告诉我,我将在GitHub上更新源代码.从具有英特尔处理器的真实Android设备看到结果会特别有趣.

2013年7月26日更新

只是一个快速更新,由基准应用程序使用最新的Xamarin.Android 4.8重新编译,以及今天发布的dot42 1.0.1.72更新 - 之前报告的结果没有重大变化.

2013年7月30日更新 - dot42的更好结果

使用我的Java代码的Robert(来自dot42制造商)端口重新测试Dot42到C#.在我最初为Xamarin完成的C#端口中,我替换了一些本地Java类,如ListArray,使用C#原生的List类,等等.Robert没有我的Dot42源代码,因此他再次从Java移植它并使用原始Java类这样的地方,有利于Dot42,我猜是因为它在Dalvik VM中运行,就像Java一样,而不是在Mono中运行,就像Xamarin一样.现在Dot42的结果要好得多.这是我测试的日志:

2013年7月30日 - Dot42在Dot42 C中测试更多Java类#

英特尔模拟器,Android 4.2

Dot42,Greg的代码使用StringBuilder.Replace()(如在Xamarin中):
总的总时间(5次运行):3646 ms,文件读取总数:3830 ms

Dot42,Greg的代码使用String.Replace()(如在Java和Robert的代码中):
总的总时间(5次运行):3027 ms,文件读取总数:3206 ms

Dot42,Robert的代码:
总计时间(5次运行):1781 ms,文件读取总数:1999 ms

Xamarin:
总时间(5次运行):1373 ms,文件读取总数:1505 ms

Java:
总计时间(5次运行):1841 ms,文件读取总计:2044 ms

ARM,三星Galaxy Note 2,省电,Android 4.1.1

Dot42,Greg的代码使用StringBuilder.Replace()(如在Xamarin中):
总的总时间(5次运行):10875 ms,文件读取总数:11280 ms

Dot42,Greg的代码使用String.Replace()(如在Java和Robert的代码中):
总的总时间(5次运行):9710 ms,文件读取总数:10097 ms

Dot42,Robert的代码:
总的总时间(5次运行):6279 ms,文件读取总数:6622 ms

Xamarin:
总时间(5次运行):6201 ms,文件读取总数:6476 ms

Java:
总计时间(5次运行):7141 ms,文件读取总计:7479 ms

我仍然认为Dot42还有很长的路要走.拥有类似Java的类(例如ArrayList)以及它们的良好性能将使得从Java到C#的代码移植稍微容易一些.但是,这是我不太可能做的事情.我宁愿使用现有的C#代码(库等),它们将使用本机C#类(例如List),并且使用当前的dot42代码执行速度很慢,并且非常适合Xamarin.

格雷格

klv*_*sov 62

是的,Xamarin的Mono虚拟机比谷歌在Android中使用的Dalvik更令人印象深刻.我用HTC Flyer和Acer Iconia Tab平板电脑对它进行了测试,通过Mono对抗Java Dalvik,对Android的C#端口进行了基准测试,使用Android的C#实现,真正打败了基于Java的Dalvik.

  • 使用正则表达式作为性能测试时要小心.RE实现中的算法差异可能会产生巨大差异.您可能正在测试的是RE的实现质量,而不是Dalvik或Mono VM.一个更好的测试是手写解析代码,它使用相同的,明显的算法,这些算法以每种语言惯用的风格编写. (14认同)
  • @gregko值得注意的是,您认为C#被更快地模拟,但Java在真实手机上更快.对我来说,这是一个重要的区别.我不担心模拟器的性能,事实上我建议你希望模拟器像真实一样慢/快.我投票重新开放了. (9认同)
  • @PeterLawrey,请看我对这个问题的更新.我打算将我现实生活中的Java代码的一部分移植到C#并运行基准测试,然后在这里发布 - 如果他们重新打开我的问题,那就是SO警察几乎立即关闭它. (4认同)
  • 如果您没有解释如何执行这些测试或测试结果,这个答案毫无价值.就像现在一样:完全基于意见. (4认同)

Chr*_*her 34

我们最近调查使用Xamarin作为应用程序.我们使用了我们已经为我们的应用程序的Windows RT版本编写的C#代码.必须为Android版本重写一些具体细节.

我们发现Xamarin C#中的I/O比Java慢大约2倍.我们的应用程序严重受I/O限制.我们还没有找到原因,但目前我们假设这是由于编组.虽然我们大多数时间都试图留在Mono VM中,但我们不知道Mono如何实际访问磁盘.

它还告诉我们的C#代码使用SQLite.NET(https://github.com/praeclarum/sqlite-net).使用SQLite.NET代码的相同提取也比使用Android的Java SQLite包装器慢2倍.看完源代码后,它似乎直接绑定到C .dll,所以我不知道它为什么这么慢.一种可能性是,从原生到Java的编组可能在Android上比在Xamarin上使用C#本机更快.


Dan*_*iel 34

这是我想与您分享的另一篇更新的博客文章.他将Xamarin与IO和Android上的本机代码和Cordova进行了比较.

简而言之,Xamarin有时比本机代码更好.他测试了应用程序大小,加载时间,从Azure服务加载列表和素数计算.

请享用!

编辑:我更新了死链接,我注意到有第2部分


Bur*_*ito 11

以下是我在以下两个设备上的本机,Xamarin和Xamarin.Forms解决方案(测试还包括iOS性能)之间的另一个测试中发现的一些信息:

三星Galaxy A7:Android操作系统版本:6.0中央处理器:Octa-core 1.9 GHz Cortex-A53内存:3GB显示分辨率:1920×1080

iPhone 6s:iOS版本:10.3.3中央处理器:双核1.84 GHz Twister RAM:2 GB显示分辨率:1334×750

比较几个常见的功能,每个功能都有自己的应用程序:

- Basic “Hello World”
- REST API
- JSON Serialization/Deserialization
- Photo Loading
- SQL Database Insert and Get All
Run Code Online (Sandbox Code Playgroud)

每次测试重复几次,图表显示平均结果.


你好,世界

基本的Hellow世界表现比较


Rest API

一组测试旨在测量应用程序通过REST API发送请求所需的时间,并使用OpenWeatherMap API无需进一步数据处理即可接收响应.

Rest API性能比较


JSON操作 测试使用Newtonsoft Json.net框架在所有Xamarin应用程序中序列化和反序列化JSON对象.使用两个Java库测试本机Android序列化和反序列化:Jackson和GSON.

进行了两次运行,一次是从头开始,另一次是缓存的信息和操作

第一次运行 :

首次运行JSON序列化

首先运行JSON反序列化

(本机iOS JSON操作正在杀死此测试btw,而Xamarin在第二次加入它)

JSON序列化第二次运行

JSON反序列化第二次运行


照片操作

首先加载具有三种不同分辨率的图像:

Resolution – 858×569, Size – 868Kb
Resolution – 2575×1709, Size – 8Mb
Resolution – 4291×2848, Size – 28.9Mb
Run Code Online (Sandbox Code Playgroud)

Image First加载Android

Image首先加载iOS

对于此测试的Xamarin.Forms结果似乎不确定,因此它不包含在图表中.


SQLite操作

测试了两个操作:

BulkInsert: Loading rows of data into a database table.
GetAll: Retrieving all data from the database.
Run Code Online (Sandbox Code Playgroud)

数据库有10,000条记录.所有操作都在设备内部处理.

SQLite Android表现

SQLite iOS表现


Xamarin Native(Xamarin.iOS/Xamarin.Android)显示自己是本机代码的相当不错的替代品,而Xamarin.Forms在很多情况下似乎很慢,但它可以是一个非常好的解决方案,可以快速开发真正简单的应用程序.

完整测试来自此来源:

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

谢谢你给我解释来增强我的答案,希望这有点帮助:)


Rol*_*f ツ 7

性能

如果您没有定义性能的含义,那么性能就是一个模糊的词,如果它是简单的计算性能,则Xamarin可能会比Java更快,具体取决于计算的性质。

Android nativly附带了多种形式以执行以下代码:

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

很明显,当执行代码时,解决方案越本地化,解决方案将越快。基于运行时的语言永远不会击败直接在CPU上运行的语言。

但是,另一方面,如果您想衡量实际的使用性能,则Java比Xamarin更快。

Xamarin及其为何会变慢

将Xamarin与普通的旧Java应用程序进行比较时,Xamarin的性能可能会更快,因为它可能会更慢。

在实际示例中,Xamarin应用程序很可能比Java应用程序慢,因为许多Android / Java(系统)调用需要使用所谓的绑定与Xamarin运行时进行委托。

有几种不同类型的绑定需要了解:

  • JNI(Java本机接口):在许多android应用程序中用于在Java代码(SDK)和本机C ++代码(NDK)之间进行接口的绑定。
  • MCW(托管可调用包装程序): Xamarin中可用的绑定,用于从托管C#代码到Java代码(Android运行时)进行接口。
  • ACW(Android可调用包装器): Xamarin中可用的绑定,可从Java代码(Android运行时)连接到托管C#代码。

有关MCW和ACW的更多信息,请访问:https//developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_1_-_understanding_the_xamarin_mobile_platform/

绑定在性能方面非常非常昂贵。从Java调用C ++方法会增加大量的调用时间,从C ++内调用C ++方法要快很多倍。

有人进行了性能测试,以计算一次JNI调用平均要花费多少Java操作:进行JNI调用的定量开销是多少?

但是不仅JNI调用成本很高,往返MCW和ACW的调用也很昂贵。现实世界中的Xamarin应用程序使用绑定进行了许多调用,由于在现实世界中Xamarin应用程序的使用可能(并且通常会)比普通的旧Java应用程序慢。但是,根据Xamarin应用程序的设计方式,用户很可能根本不会注意到差异。

TLDR /结论: Xamarin需要使用各种类型的绑定,这很耗时。

除了绑定之外,在谈论实际性能时还涉及许多其他因素,例如:二进制文件的大小,将应用程序加载到内存中,I / O操作等等。可以在此处找到调查其中一些内容的博客文章:https : //magenic.com/thinking/mobile-development-platform-performance-part-2-native-cordova-classic-xamarin-xamarin-forms