我看到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个不同设备和一个模拟器的总时间如下所示。我只测试了“发布”版本,没有启用调试。

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

Java: Grand总时间(5次运行):12361毫秒,文件读取总时间:13304毫秒

c#:总时间(5次运行):17504毫秒,文件读取总时间:17956毫秒

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

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

c#:总时间(5次运行):9884毫秒,文件读取总时间:10247毫秒

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

Java: Grand总时间(5次运行):9742毫秒,文件读取总时间:10111毫秒

c#:总时间(5次运行):10459毫秒,文件读取总时间:10696毫秒

模拟器-英特尔(Android 4.2, API 17)

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

c#:总时间(5次运行):2049毫秒,文件读取总时间:2182毫秒

模拟器- Intel (Android 2.3.7, API 10)

Java: Grand总时间(5次运行):2992毫秒,文件读取总时间:3591毫秒

c#:总时间(5次运行):2049毫秒,文件读取总时间:2257毫秒

模拟器- Arm (Android 4.0.4, API 15)

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

c#:总时间(5次运行):44136毫秒,文件读取总时间:45109毫秒

简短的讨论

我的测试代码主要包含文本解析、替换和Regex搜索,也许对于其他代码(例如更多的数值操作),结果会有所不同。在所有带有ARM处理器的设备上,Java的性能都优于Xamarin c#代码。最大的不同是在Android 2.3下,c#代码运行在大约。Java速度的70%。

在Intel模拟器上(使用Intel HAX技术,模拟器以快速virt模式运行),Xamarin c#代码运行我的示例代码要比Java快得多——大约快1.35倍。也许Mono虚拟机代码和库在Intel上比在ARM上优化得更好?

编辑2013年7月8日

我刚刚安装了Genymotion Android模拟器,它在Oracle VirtualBox中运行,同样,这个使用本机英特尔处理器,而不是模拟ARM处理器。与Intel HAX模拟器一样,c#在这里运行得更快。以下是我的结果:

Genymotion模拟器- Intel (Android 4.1.1, API 16)

Java: 总时间(5次运行):2069毫秒,文件读取总时间:2248毫秒 c#: 总时间(5次运行):1543毫秒,文件读取总数:1642毫秒

然后我注意到Xamarin有更新。Android beta版本4.7.11,发布说明中提到了Mono运行时的一些变化。决定快速测试一些ARM设备,有一个大惊喜——c#数字提高了:

BN Nook XD+, ARM (Android 4.0)

Java: Grand总时间(5次运行):8103 ms,文件读取总时间:8569 ms c#:总时间(5次运行):7951毫秒,文件读取总时间:8161毫秒

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

三星Galaxy Note 2 - ARM (Android 4.1.1)

Java:总时间(5次运行):9675毫秒,文件读取总时间:10028毫秒 c#:总时间(5次运行):9911毫秒,文件读取总时间:10104毫秒

这里的c#似乎只是稍微慢了一点,但这些数字让我犹豫了一下:为什么Note 2的处理器更快,但运行时间却比Nook HD+要长?答案是:节电模式。在Nook上,它是禁用的,在Note 2上是启用的。决定在禁用省电模式的情况下测试(与启用省电模式一样,它也会限制处理器的速度):

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

Java: Grand总时间(5次运行):7153毫秒,文件读取总时间:7459毫秒 c#:总时间(5次运行):6906毫秒,文件读取总时间:7070毫秒

现在,令人惊讶的是,c#在ARM处理器上也比Java略快。大的改进!

编辑2013年7月12日

我们都知道,没有什么能比本机代码更快,我对我在Java或c#中的句子分配器的性能并不满意,特别是我需要改进它(从而使它更慢)。决定用c++重写。以下是我在Galaxy Note 2上禁用省电模式时本机和Java速度的一个小比较(由于其他原因,文件集比以前的测试要小):

Java: 总时间(5次运行):3292毫秒,文件读取总数:3454毫秒

本地经验法则: 总时间(5次运行):537毫秒,文件读取总时间:657毫秒

本机的胳膊: 总时间(5次运行):458 ms,文件读取总时间:587 ms

看起来对于我的特定测试,本机代码比Java快6到7倍。警告:不能在Android上使用std::regex类,所以必须自己编写专门的例程来搜索段落中断或html标签。我最初在PC上使用regex测试相同的代码,比Java快4到5倍。

唷!用char*或wchar*指针再次唤醒原始内存,我立刻感觉自己年轻了20岁!:)

编辑2013年7月15日

(请参见下面,2013年7月30日的编辑,Dot42的更好的结果)

With some difficulty, I managed to port my C# tests to Dot42 (version 1.0.1.71 beta), another C# platform for Android. Preliminary results show that Dot42 code is about 3x (3 times) slower than Xamarin C# (v. 4.7.11), on an Intel Android emulator. One problem is that System.Text.RegularExpressions class in Dot42 does not have the Split() function that I used in Xamarin tests, so I used Java.Util.Regex class instead, and Java.Util.Regex.Pattern.Split(), so in this particular place in the code, there is this small difference. Should not be a big problem though. Dot42 compiles to Dalvik (DEX) code, so it cooperates with Java on Android natively, does not need expensive interop from C# to Java like Xamarin.

为了比较,我也在ARM设备上运行测试——这里的Dot42代码“仅”比Xamarin c#慢2倍。以下是我的结果:

HTC Nexus One Android 2.3.7 (ARM)

Java: Grand总时间(5次运行):12187毫秒,文件读取总时间:13200毫秒 Xamarin c#:总时间(5次运行):13935毫秒,文件读取总时间:14465毫秒 Dot42 c#:总时间(5次运行):26000 ms,文件读取总时间:27168 ms

三星Galaxy Note 2, Android 4.1.1 (ARM)

Java: Grand总时间(5次运行):6895毫秒,文件读取总时间:7275毫秒 Xamarin c#:总时间(5次运行):6466毫秒,文件读取总时间:6720毫秒 Dot42 c#:总时间(5次运行):11185毫秒,文件读取总时间:11843毫秒

Intel模拟器,Android 4.2 (x86)

Java:总时间(5次运行):2389 ms,文件读取总时间:2770 ms Xamarin c#:总时间(5次运行):1748毫秒,文件读取总时间:1933毫秒 Dot42 c#:总时间(5次运行):5150毫秒,文件读取总时间:5459毫秒

对我来说,同样有趣的是,Xamarin c#在新的ARM设备上比Java略快,而在旧的Nexus One上略慢。如果有人也想运行这些测试,请告诉我,我会在GitHub上更新源代码。如果能看到搭载英特尔处理器的真正Android设备的结果,那将是非常有趣的。

更新7/26/2013

只是一个快速更新,用最新的Xamarin重新编译了基准应用程序。Android 4.8,以及今天发布的dot42 1.0.1.72更新-与之前报告的结果相比没有显著变化。

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

重新测试Dot42与罗伯特(从Dot42制造商)的端口我的Java代码到c#。在我最初为Xamarin所做的c#移植中,我用c#原生的List类替换了一些原生Java类,如lisstarray等。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非常好。

Greg


当前回答

I came across this interesting post

https://medium.com/@harrycheung/mobile-app-performance-redux-e512be94f976#.kfbauchtz

希望这些信息能有所帮助。

其他回答

I came across this interesting post

https://medium.com/@harrycheung/mobile-app-performance-redux-e512be94f976#.kfbauchtz

希望这些信息能有所帮助。

我们最近在一款应用中使用了Xamarin。我们使用了之前为Windows RT版本应用编写的c#代码。为了Android版本,我们不得不重写了一些具体细节。

我们发现Xamarin c#中的I/O大约比Java慢2倍。我们的应用程序受到严重的I/O限制。我们还没有发现造成这种情况的原因,但目前我们假设这是由于编组。虽然我们大部分时间都在Mono VM中,但我们不知道Mono实际上是如何访问磁盘的。

这也说明我们的c#代码使用SQLite。网(https://github.com/praeclarum/sqlite-net)。使用SQLite进行相同的获取。NET代码也比使用Android的Java SQLite包装器慢2倍。在查看源代码后,它似乎直接绑定到C .dll,所以我不知道为什么它这么慢。一种可能是,在Android上从原生到Java的字符串封送比在Xamarin上从原生到c#的字符串更快。

这是一个很老的测试,但可能是相关的:https://github.com/EgorBo/Xamarin.Android-vs-Java

算法测试

集合、泛型、自定义值类型

使用字符串

UPD:谷歌Pixel 2的新数据(谢谢youssha -aleayoub)

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

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

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

比较了一些共同的特点,每一个都有自己的应用:

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

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


你好世界


火休息

一组测试,旨在测量应用程序通过REST API发送请求并在不进行进一步数据处理的情况下,使用OpenWeatherMap API接收响应所需的时间。


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

执行了两次运行,第一次从头开始,第二次使用缓存的信息和操作

第一次运行:

(顺便说一下,原生iOS JSON Operations正在杀死这个测试,Xamarin在第二个测试中加入了它)


图片操作

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

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

关于沙玛林似乎有些不确定。生成此测试的结果,因此不包括在图中。


SQLite操作

测试了两个操作:

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

数据库有10,000条记录。所有操作都在设备内部进行。


Xamarin Native (Xamarin. ios /Xamarin. android)显示自己是原生代码的很好的替代品,而Xamarin。表单在很多情况下似乎很慢,但对于快速开发非常简单的应用程序来说,它是一个非常好的解决方案。

完整的测试来自此来源:

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

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

性能

如果不定义性能的含义,性能是一个模糊的词,如果只是简单的计算性能,Xamarin可以比Java快,这取决于计算的性质。

Android自带多种表单来执行代码:

RenderScript (CPU和GPU) Java (SDK) c++ (NDK) OpenGL (GPU)

很明显,在执行代码时,解决方案越原生,速度就越快。基于运行时的语言永远不会胜过直接运行在CPU上的语言。

但另一方面,如果你想衡量现实生活中的使用性能,Java可能比Xamarin更快。

沙玛林以及它为什么会变慢

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

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

有几种不同类型的绑定是很重要的:

JNI (Java本机接口):在许多android应用程序中使用的绑定,用于Java代码(SDK)和本机c++代码(NDK)之间的接口。 MCW(托管可调用包装器):Xamarin中可用的绑定,用于从托管c#代码到Java代码(Android运行时)的接口。 ACW (Android Callable Wrappers): 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