我遇到Xamarin声称他们在Android上的Mono实现和他们的C#编译应用程序比Java代码更快.有没有人在不同的Android平台上对非常相似的Java和C#代码执行实际基准来验证此类声明,是否可以发布代码和结果?
2013年6月18日新增
由于没有答案,也找不到其他人做的基准,所以决定自己做测试.不幸的是,我的问题仍然是“锁定”,所以我不能将其作为答案发布,只编辑问题.请投票重新打开这个问题.对于C#,我使用了Xamarin.Android Ver. 4.7.09001(测试版).源代码,我用于测试和编译的APK包的所有数据都在GitHub上:
如果有人想在其他设备或模拟器上重复我的测试,我也有兴趣了解结果.
我的测试结果
我将我的句子提取器类移植到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:
Grand total time (5 runs): 2069 ms, with file reading total: 2248 ms
C#:
Grand total time (5 runs): 1543 ms, with file reading total: 1642 ms
然后我注意到Xamarin.Android beta版本4.7.11有更新,发行说明也提到了Mono运行时的一些变化.决定快速测试一些ARM设备,并且大惊喜–C#数字得到改善:
BN Nook XD,ARM(Android 4.0)
Java: Grand total time (5 runs): 8103 ms, with file reading total: 8569 ms
C#: Grand total time (5 runs): 7951 ms, with file reading total: 8161 ms
哇! C#现在比Java好吗?决定在我的Galaxy Note 2上重复测试:
三星Galaxy Note 2 – ARM(Android 4.1.1)
Java: Grand total time (5 runs): 9675 ms, with file reading total: 10028 ms
C#: Grand total time (5 runs): 9911 ms, with file reading total: 10104 ms
这里的C#似乎只是稍微慢一点,但这些数字给了我一个停顿:为什么时间比Nook HD更长,即使Note 2有更快的处理器?答案:省电模式.在Nook上,它已被禁用,在注2 – 已启用.决定禁用省电模式进行测试(与启用时一样,它也会限制处理器速度):
三星Galaxy Note 2 – ARM(Android 4.1.1),省电禁用
Java: Grand total time (5 runs): 7153 ms, with file reading total: 7459 ms
C#: Grand total time (5 runs): 6906 ms, with file reading total: 7070 ms
现在,令人惊讶的是,C#在ARM处理器上的速度也略快于Java.大改进!
编辑2013年7月12日
我们都知道,没有什么比速度本机代码更好,我对Java或C#中的句子分割器的性能不满意,特别是我需要改进它(因此使它更慢).决定用C重写它.这是一个小的(即比以前的测试更小的文件集,出于其他原因)比较我的Galaxy Note 2上原生与Java的速度,禁用了省电模式:
Java的:
总计时间(5次运行):3292 ms,文件读数总计:3454 ms
原生拇指:
总计时间(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: Grand total time (5 runs): 12187 ms, with file reading total: 13200 ms
Xamarin C#: Grand total time (5 runs): 13935 ms, with file reading total: 14465 ms
Dot42 C#: Grand total time (5 runs): 26000 ms, with file reading total: 27168 ms
三星Galaxy Note 2,Android 4.1.1(ARM)
Java: Grand total time (5 runs): 6895 ms, with file reading total: 7275 ms
Xamarin C#: Grand total time (5 runs): 6466 ms, with file reading total: 6720 ms
Dot42 C#: Grand total time (5 runs): 11185 ms, with file reading total: 11843 ms
英特尔模拟器,Android 4.2(x86)
Java: Grand total time (5 runs): 2389 ms, with file reading total: 2770 ms
Xamarin C#: Grand total time (5 runs): 1748 ms, with file reading total: 1933 ms
Dot42 C#: Grand total time (5 runs): 5150 ms, with file reading total: 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的结果要好得多.这是我测试的日志:
7/30/2013 – Dot42 tests with more Java classes in Dot42 C#
Intel emulator, Android 4.2
Dot42, Greg’s Code using StringBuilder.Replace() (as in Xamarin):
Grand total time (5 runs): 3646 ms, with file reading total: 3830 ms
Dot42, Greg’s Code using String.Replace() (as in Java and Robert’s code):
Grand total time (5 runs): 3027 ms, with file reading total: 3206 ms
Dot42, Robert’s Code:
Grand total time (5 runs): 1781 ms, with file reading total: 1999 ms
Xamarin:
Grand total time (5 runs): 1373 ms, with file reading total: 1505 ms
Java:
Grand total time (5 runs): 1841 ms, with file reading total: 2044 ms
ARM, Samsung Galaxy Note 2, power saving off, Android 4.1.1
Dot42, Greg’s Code using StringBuilder.Replace() (as in Xamarin):
Grand total time (5 runs): 10875 ms, with file reading total: 11280 ms
Dot42, Greg’s Code using String.Replace() (as in Java and Robert’s code):
Grand total time (5 runs): 9710 ms, with file reading total: 10097 ms
Dot42, Robert’s Code:
Grand total time (5 runs): 6279 ms, with file reading total: 6622 ms
Xamarin:
Grand total time (5 runs): 6201 ms, with file reading total: 6476 ms
Java:
Grand total time (5 runs): 7141 ms, with file reading total: 7479 ms
我仍然认为Dot42还有很长的路要走.拥有类似Java的类(例如ArrayList)以及它们的良好性能会使代码从Java移植到C#稍微容易一些.但是,这是我不太可能做的事情.我宁愿使用现有的C#代码(库等),它们将使用本机C#类(例如List),并且使用当前的dot42代码执行速度很慢,而且Xamarin也很好.
格雷格