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

时间:2013-06-16 14:52:37

标签: c# java android xamarin dot42

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

于2013年6月18日添加

由于没有答案,也找不到其他人做过的基准测试,所以决定自己做测试。不幸的是,我的问题仍然是“锁定”#34;所以我不能发布这个作为答案,只编辑问题。请投票重新打开这个问题。对于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个不同设备和一个模拟器的总时间。我测试了#34;发布"仅构建,无需启用调试。

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

Samsung GT-N7100(Android 4.1.1 JellyBean,API 16) - Samsung 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#代码大约运行。 Java速度的70%。

在英特尔模拟器上(采用英特尔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)

  

爪哇:   总计时间(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的速度,禁用省电模式:

爪哇: 总计时间(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代码只有#34;而且#34;比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 maker)端口重新测试了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

     

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

     

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

     

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

     

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

     

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

     

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

     

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

     

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

     

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

     

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

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

格雷格

7 个答案:

答案 0 :(得分:60)

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

答案 1 :(得分:39)

I came across this interesting post

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

Android App Performance

iOS App Performance

希望这些信息有所帮助。

答案 2 :(得分:33)

This is another more updated blog post I would like to share with you。他将Xamarin与IO和Android上的本机代码和Cordova进行了比较。

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

享受!

编辑:我更新了死链接,我注意到there is a part 2

答案 3 :(得分:32)

我们最近调查使用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#本机更快。

答案 4 :(得分:9)

以下是我在以下两个设备上的本机,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

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

Hello World

Basic Hellow World performance comparison

Rest API

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

Rest API performance comparison

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

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

首先运行:

JSON serialization first run

JSON deserialization first run

(原生iOS JSON操作正在杀死这个测试btw,Xamarin在第二次加入它)

JSON Serialization second run

JSON Deserialization second run

照片操作

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

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

Image First Load Android

Image First Load iOS

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

SQLite操作

测试了两个操作:

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

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

SQLite Android performances

SQLite iOS performances

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/

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

答案 5 :(得分:5)

效果

如果你没有定义你的性能是什么意思,性能是一个模糊的词,如果它是简单的计算性能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 Native Interface):许多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操作数量:What is the quantitative overhead of making a JNI call?

但是,不仅JNI呼叫成本高昂,因此来往MCW和ACW的呼叫也是如此。真实世界的Xamarin应用程序使用绑定进行许多调用,因为Xamarin应用程序的这种现实世界使用可能(并且通常)比普通的旧Java应用程序慢。但是,根据Xamarin应用程序的设计方式,用户很可能甚至不会注意到差异。

TLDR /结论: Xamarin需要使用al sorts绑定,这是时间成本。

  

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

答案 6 :(得分:1)

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

算术测试

enter image description here

收藏集,泛型,自定义值类型

enter image description here

使用字符串

enter image description here

UPD: Google Pixel 2的新数据(感谢yousha-aleayoub

Pixel 2 tests