是否有人有基准(代码和结果)可以比较用Xamarin C#和Java编写的Android应用的性能?[关闭]


544

我偶然发现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种不同设备和1个模拟器的总时间。我仅测试了“发布”版本,而未启用调试。

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

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

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

三星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

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

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

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

简短讨论

我的测试代码主要包含文本解析,替换和Regex搜索,也许对于其他代码(例如更多的数字运算),结果将有所不同。在所有装有ARM处理器的设备上,Java的性能均优于Xamarin C#代码。最大的区别是在Android 2.3下,其中C#代码的运行速度大约为2。Java速度的70%。

在英特尔仿真器(采用英特尔HAX技术,仿真器以快速virt模式运行)上,Xamarin C#代码运行示例代码的速度比Java快得多-大约快1.35倍。也许Mono的虚拟机代码和库在Intel上比在ARM上优化得更好?

编辑2013年7月8日

我刚刚安装了Genymotion Android模拟器,该模拟器在Oracle VirtualBox中运行,并且再次使用本地Intel处理器,而不是ARM处理器。与Intel HAX模拟器一样,C#在这里的运行速度也更快。这是我的结果:

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

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

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

然后,我注意到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上已启用。决定在禁用节能模式的情况下进行测试(与启用一样,它也限制了处理器速度):

Samsung Galaxy Note 2-ARM(Android 4.1.1),已禁用节能功能

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

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

现在,令人惊讶的是,在ARM处理器上,C#也比Java快一点。大进步!

编辑2013年7月12日

我们都知道,没有什么能比本地代码更好地提高速度了,我对我的Java或C#语句分割器的性能不满意,特别是我需要对其进行改进(使其变得更慢)。决定用C ++重写它。这是我的Galaxy Note 2上本机与Java速度比较小的结果(出于其他原因,文件集比以前的测试要小),并且禁用了省电模式:

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

本地拇指:总计总时间(5次运行):537毫秒,文件读取总计:657毫秒

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

看起来对于我的特定测试,本机代码比Java快6至7倍。警告:无法在Android上使用std :: regex类,因此不得不编写自己的专用例程来搜索段落分隔符或html标签。我在使用regex的PC上对相同代码进行的初始测试大约比Java快4至5倍。

!再次用char *或wchar *指针唤醒原始内存,我立即感到年轻了20岁!:)

编辑2013年7月15日

(请参阅下面的内容,并于2013年7月30日进行了修改,使用Dot42可获得更好的效果)

遇到了一些困难,我设法将C#测试移植到另一个适用于Android的C#平台Dot42(版本1.0.1.71 beta)。初步结果显示,在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设备的结果将特别有趣。

更新7/26/2013

只是一个快速更新,由基准应用重新编译为最新的Xamarin.Android 4.8,并且今天发布了dot42 1.0.1.72更新-与以前报告的结果相比,没有重大变化。

更新7/30/2013-dot42的更好结果

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

7/30/2013-Dot42在Dot42 C#中使用更多Java类进行测试

英特尔模拟器,Android 4.2

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

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

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

Xamarin:
总计时间(5次运行):1373毫秒,文件读取总计:1505毫秒

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

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

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

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

Dot42,罗伯特的代码:
总计时间(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来说效果很好。

格雷格


5
Nexus 7 4.2.2的调试模式,对字符串和xamarin alpha 9进行了一些优化:总时间:3907毫秒,文件读取总数:4016。什么意思是“ 5次运行”?
Softlion

1
“此问题可能会引发辩论,争论,民意测验或进一步的讨论” <-参见上文;)
LearnCocos2D

2
@ LearnCocos2D-我只报告具体的结果和数字,即事实。先生们不要争辩事实:)
gregko

2
好吧,科学家们这样做;)观察到的行为与事实之间存在差异。要成为事实还有很多,甚至在那时,对其他用户/情况的适用性仍然值得怀疑。这是基准的症结所在,它们只是表面上的事实-直到您发现供应商x针对特定基准应用优化了其驱动程序。与此相关的是,曾经证明水具有记忆力(即顺势疗法测试),在考虑并排除了测试者的偏见后,水没有记忆力,因此它没有显示任何统计学意义。
LearnCocos2D 2013年

3
另外,在下一个+0.1版本中,这些性能特征可能会发生显着变化-那时,您在此处所做的所有努力都会从“事实”变为“无聊”。但是,任何来这里的人都可能将其视为事实,并得出错误的结论。基准的另一个关键点:它们仅在给定的时间和所使用软件的版本中具有代表性。第二天,它们可能不再反映现实。您必须继续重新测试结果。这就是为什么这里的结果可以被认为是主观的,几乎没有意义的原因。
LearnCocos2D 2013年

Answers:


62

是的,Xamarin的Mono虚拟机比Android中使用的Google Dalvik更令人印象深刻。我已经使用HTC Flyer和Acer Iconia Tab平板电脑对其进行了测试,以通过Mono对Java Dalvik进行Mono测试来比较Android的C#端口,并很好地实现了Android的C#实现,并且真正击败了基于Java的Dalvik。


4
@PeterLawrey,请参阅我对问题的更新。我确实打算将我现实生活中的Java代码的一部分移植到C#并运行基准测试,然后将其发布到此处-如果它们重新打开了我的问题,即SO警官几乎立即关闭了它。
gregko 2013年

1
@PeterLawrey-我现在进行了测试并将结果发布在StackOverflow上,但是在问题本身内,因为它仍然保持“锁定”并且无法发布答案。如果可以的话,请增加您的投票以再次提出问题。结果很有趣,在ARM Java上胜出,在Intel上-Mono中的C#代码要快得多。
gregko

9
@gregko值得注意的是,您看到C#的仿真速度更快,但是Java在真实手机上的速度更快。对我来说,这是一个重要的区别。我不必担心模拟器的性能,实际上,我建议您希望模拟器与真实事物一样慢/快。我已投票决定重新开放。
彼得·劳瑞

14
在使用正则表达式作为性能测试时要小心。RE实现中的算法差异可能会产生巨大差异。上面您可能要测试的是RE的实现质量,而不是Dalvik或Mono VM。更好的测试是手写的解析代码,该代码使用以每种语言惯用的风格编写的相同,显而易见的算法。
Christopher

4
如果没有关于如何执行这些测试或测试结果的任何解释,此答案毫无价值。现在:完全基于意见。
罗夫·ツ2015年


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,所以我不知道为什么它这么慢。一种可能是,在Xamarin上,Android上将字符串从本地编组到Java可能比C#本地编排更快。


1
这也很可能是由于Xamerin需要与“绑定”与系统进行交互。默认情况下,每个系统调用都属于Java类,但需要将其委派给Mono VM,这需要花费时间。反之亦然。我在回答中对此做了更多解释:stackoverflow.com/a/46973819/1052697
罗夫(Rolf)2010年


11

这是我在本机Xamarin和Xamarin之间进行的另一项测试中找到的一些信息。在以下两个设备上的Forms解决方案(测试还包括iOS性能):

Samsung Galaxy A7:Android操作系统版本:6.0中央处理单元:八核1.9 GHz Cortex-A53 RAM: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

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


你好,世界

Hellow World基本性能比较


REST API

使用OpenWeatherMap API进行的一组测试,旨在测量应用程序通过REST API发送请求并接收回传响应所花费的时间,而无需进一步的数据处理。

REST API性能比较


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

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

第一次运行 :

JSON序列化首次运行

JSON反序列化首次运行

(本机iOS JSON操作正在终止此测试,而Xamarin将在第二个测试中加入它)

JSON序列化第二次运行

JSON反序列化第二次运行


照片操作

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

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

图像首次加载Android

图像首次加载iOS

对于此测试的Xamarin.Forms结果似乎有些不确定,因此未包含在图中。


SQLite操作

测试了两个操作:

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

具有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/

谢谢您给我一些解释,以增强答案,希望这对您有所帮助:)


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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.