我遇到了Xamarin声称他们在Android上的Mono实现和他们的C#编译的应用程序比Java代码更快。有没有人在不同的Android平台上执行非常类似的Java和C#代码的实际基准来验证此类声明,可以发布代码和结果?
于2013年6月18日添加
因为没有答案,没有人能找到这样的基准,决定做我自己的测试。不幸的是,我的问题仍然是“锁定”,所以我不能发布这个答案,只有编辑的问题。请投票重新开启此问题。对于C#,我使用Xamarin.Android ver。 4.7.09001(beta)。源代码,我用于测试的所有数据和编译的APK包都在GitHub上:
如果有人想在其他设备或仿真器上重复我的测试,我也有兴趣了解结果。
我的测试结果
我将我的句子提取器类移植到C#(从我的@Voice Aloud Reader应用程序),并对英语,俄语,法语,波兰语和捷克语的10个html文件运行一些测试。每次运行在所有10个文件上执行5次,并且3个不同的设备和一个模拟器的总时间在下面发布。我测试了“发布”构建,而不启用调试。
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毫秒,文件读取总计:9186毫秒
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毫秒,文件读取总计:3127毫秒
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速度。
在Intel模拟器(使用Intel HAX技术,仿真器以快速virt模式运行)中,Xamarin C#代码运行我的示例代码比Java快得多 – 大约1.35倍的时间。也许Mono虚拟机代码和库在英特尔比在ARM上更好的优化?
编辑2013年7月8日
我刚刚安装了Genymotion Android模拟器,它运行在Oracle VirtualBox,再次这个使用本机英特尔处理器,而不是模拟ARM处理器。和英特尔HAX模拟器一样,C#的运行速度也快得多。这里是我的结果:
Genymotion模拟器 – Intel(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。这里是一个小(即一组较小的文件比以前的测试,由于其他原因)比较本机的速度与Java在我的Galaxy Note 2,禁用省电模式:
Java:
总计时间(5次运行):3292 ms,文件读取总计:3454 ms
本机拇指:
总计时间(5次运行):537 ms,文件读取总计:657 ms
本机臂:
总计时间(5次运行):458 ms,文件读取总计:587 ms
看起来像我的特定测试,本机代码是Java的6到7倍。注意:不能在Android上使用std :: regex类,所以不得不编写我自己的专门例程搜索段落或html标签。我使用regex在PC上对同一代码进行初始测试,比Java快4到5倍。
!!再次使用char *或wchar *指针唤醒原始内存,我立即感到20岁了! 🙂
修改2013年7月15日
(请参阅下面,与编辑7/30/2013,使用Dot42更好的结果)
有一些困难我管理我的C#测试到Dot42(版本1.0.1.71测试版),另一个C#平台Android。初步结果显示,在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本地协作,不需要从C#到XAMarin的昂贵的互操作。
为了比较,我还在ARM设备上运行测试 – 这里Dot42代码是“只”比Xamarin C#慢两倍。这里是我的结果:
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设备与英特尔处理器的结果。
更新7/26/2013
只是一个快速更新,重新编译的基准测试应用程序与最新的Xamarin.Android 4.8,以及dot42 1.0.1.72更新发布今天 – 没有重大变化从以前报告的结果。
更新7/30/2013 – 更好的结果dot42
重新测试Dot42与我的Java代码的罗伯特(从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。
格雷格