首页 文章

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

提问于
浏览
504

我遇到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个不同设备和一个模拟器的总时间 . 我只测试了“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:总计时间(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毫秒

现在,令人惊讶的是,C#在ARM处理器上的速度也略快于Java . 大改进!

编辑2013年7月12日

我们都知道,没有什么比速度本机代码更好,我对Java或C#中的句子分割器的性能不满意,特别是我需要改进它(从而使它更慢) . 决定用C重写它 . 这是一个小的(即比以前的测试更小的文件集,出于其他原因)比较我的Galaxy Note 2上原生与Java的速度,禁用了省电模式:

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日

(Please see below, with edits of 7/30/2013, for much better results with 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:总时间(5次运行):12187 ms,文件读取总数:13200 ms Xamarin C#:总计时间(5次运行):13935 ms,文件读取总计:14465 ms Dot42 C#:总计时间(5运行):26000毫秒,文件读数总计:27168毫秒

三星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毫秒,文件读数总计:11843毫秒

英特尔模拟器,Android 4.2(x86)

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

对我来说,值得注意的是,Xamarin C#在较新的ARM设备上略快于Java,在旧的Nexus One上略慢 . 如果有人想要运行这些测试,请告诉我,我将在GitHub上更新源代码 . 从具有Intel处理器的真实Android设备看到结果会特别有趣 .

更新2013年7月26日

只是一个快速更新,由最新的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,我猜是因为它在Dalvik VM中运行,就像Java一样,而不是在Mono中运行,就像Xamarin一样 . 现在Dot42的结果要好得多 . 这是我测试的日志:

7/30/2013 - Dot42使用Dot42 C#Intel模拟器,Android 4.2 Dot42,使用StringBuilder的Greg代码(如Xamarin)测试更多Java类:总计大时间(5次运行):3646 ms,带文件阅读总数:3830 ms Dot42,Greg的代码使用String.Replace()(如Java和Robert的代码):总计时间(5次运行):3027 ms,文件读取总数:3206 ms Dot42,Robert的代码:总计时间(5次运行):1781 ms,文件读取总数:1999 ms Xamarin:总计时间(5次运行):1373 ms,文件读取总计:1505 ms Java:总计时间(5次运行):1841 ms,带文件阅读总数:2044 ms ARM,三星Galaxy Note 2,省电,Android 4.1.1 Dot42,Greg的代码使用StringBuilder.Replace()(如Xamarin):总计时间(5次运行):10875 ms,带文件读取总计:11280 ms Dot42,Greg的代码使用String.Replace()(如Java和Robert的代码所示):Grand总时间(5次运行):9710 ms,文件读数总计:10097 ms Dot42,Robert代码:总计时间(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也很好 .

格雷格

7 回答

  • 32

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

    Arithmetic test

    Collections, generics, custom value types

    Working with strings

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

  • 32

    表现

    如果你没有定义你的性能是什么意思,性能是一个模糊的词,如果它是简单的计算性能Xamarin可能比Java更快,具体取决于计算的性质 .

    Android本身带有多种形式来执行代码:

    • 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 (Managed Callable Wrappers): 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/Conclusion: Xamarin需要使用al sorts绑定,这是时间成本高昂的 .

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

  • 36

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

    Samsung 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


    Rest API

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


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

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

    第一次运行 :

    (本机iOS JSON Operations正在杀死这个测试btw,而Xamarin在第二次加入它


    Photo Operations

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

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

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


    SQLite Operations

    测试了两个操作:

    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.Forms在很多情况下似乎很慢,但它可以是一个非常好的解决方案,可以快速开发真正简单的应用程序 .

    完整测试来自此来源:

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

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

  • 1

    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

  • 4

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

  • 8

    我们最近调查使用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 's Java SQLite wrapper. After looking at the source code, it appears to bind directly to the C .dll, so I do not know why it'慢得多2倍 . 一种可能性是,从原生到Java的编组可能在Android上比在Xamarin上使用C#本机更快 .

  • 58
    I came across this interesting post
    

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

    希望这些信息有所帮助

相关问题