Scala在Android上的性能表现

16

我刚开始学习Scala,学起来很有趣。今天我也听说了Scala for Android,完全被吸引住了。

然而,考虑到Scala有点像Java的超集,即Java++(我的意思是Java包含更多东西),我想知道Scala代码在Android上如何工作?

此外,如果使用Scala编写Android应用程序,应用程序的性能会受到影响吗?也就是说,如果需要额外的工作来解释Scala代码。

4个回答

41

稍微解释一下@Aneesh的回答——是的,没有额外的工作来解释Scala字节码,因为它与Java字节码完全相同

Enter image description here

请注意,当您在安卓上运行代码时,还存在一个 Java 字节码 => Dalvik 字节码步骤。

但是使用相同的砖块,一个人可以建造一个自行车棚,而另一个人可以建造一个市政厅。例如,由于该语言鼓励不可变性,Scala 生成了大量的短暂对象。对于成熟的 JVM(如HotSpot)来说,这已经十年没什么问题了。但对于 Dalvik 来说,这是一个问题 (在最近版本之前,对象池和紧密重复使用已创建对象是 Java 中最常见的性能提示之一)。

接下来,写 val 就不同于写 final Foo bar = ...。在内部,这段代码表示为一个字段 + getter(除非您在 val 前缀中添加 private [this],这将转换为通常的 final 字段)。var 被转换为字段 + getter + setter。这为什么很重要?

在Android 2.2之前的旧版本中根本没有JIT,因此这会导致与直接字段访问相比约为3倍至7倍的惩罚。最后,虽然Google建议避免使用内部类并优先选择包, 但即使您不编写内部类,Scala也会创建许多内部类。考虑以下代码:

object Foo extends App {
    List(1,2,3,4)
      .map(x => x * 2)
      .filter(x => x % 3 == 0)
      .foreach(print)
}

会创建多少个内部类?你可能会说没有,但如果你运行scalac,你会看到:

Foo$$anonfun$1.class       // Map
Foo$$anonfun$2.class       // Filter
Foo$$anonfun$3.class       // Foreach
Foo$.class                 // Companion object class, because you've used `object`
Foo$delayedInit$body.class // Delayed init functionality that is used by App trait
Foo.class                  // Actual class

因此,如果您使用大量不可变性和语法糖编写习惯性的Scala代码,可能会有一些惩罚。问题在于它高度依赖于您的部署(是否针对较新的设备?)和实际的代码模式(您始终可以返回到Java或至少在性能关键点上编写不太习惯的代码),其中一些问题将由语言本身(最后一个)在下一个版本中解决。

原始图片 来源为维基百科

另请参阅Stack Overflow问题在Android上使用Scala值得吗?会有很多开销吗?存在问题吗?,可能会在开发过程中遇到一些问题。


惊人的见解!从未想到内部类在某些情况下可能是多余的负担。 - Dragonborn

5
虽然Scala“会正常工作”,因为它像Java一样编译成字节码,但需要考虑性能问题。惯用的Scala代码往往会创建更多的临时对象,而Dalvik VM对此并不太友好。
在Android上使用Scala时,以下是需要注意的几点:
  • 向量,因为它们可能浪费空间(即使只有一个项目,也总是占用32个项目的数组)
  • 集合上的方法链接 - 在可能的情况下,应该使用.view,以避免创建冗余的集合。
  • 装箱 - 在某些情况下,如使用泛型、使用Option[Int]和某些匿名函数时,Scala将装箱您的基本类型。
  • for循环可能会浪费内存,在敏感部分考虑将其替换为while循环。
  • 隐式转换 - 像str.indexWhere(...)这样的调用将在字符串上分配包装器对象。可能会浪费空间。
  • Scala的Map每次访问键时都会分配一个Option[V]。我不得不偶尔将其替换为Java的HashMap。
当然,在使用分析器之后,您应该仅优化瓶颈处的地方。

您可以在此博客文章中阅读有关上述建议的更多信息: http://blogs.microsoft.co.il/dorony/2014/10/07/scala-performance-tips-on-android/


5
我找到了一篇关于两种语言的基准测试的论文: http://cse.aalto.fi/en/midcom-serveattachmentguid-1e3619151995344619111e3935b577b50548b758b75/denti_ngmast.pdf 我没有阅读整篇文章,但最后似乎他们会给Java一个优点:
总之,我们认为Scala语言在移动应用程序开发中将不会扮演重要角色,这是因为保持设备低能耗的重要性。Scala语言的强项是其组件的可伸缩性,而在移动设备上这并不重要,因为应用程序往往不会缩放且规模较小。
感谢来自Aalto大学的Mattia Denti和Jukka K. Nurminen。

作者既没有提供Java或Scala的任何版本信息,这使得这项研究非常可疑。 - om-nom-nom
对我来说,这似乎太过“模糊”,但这是我能找到的唯一东西。 - Enrichman
结论相当强烈,考虑到基准测试似乎略微偏向于Scala的性能,并且能源消耗差距并不是很大。在两个测试中,Scala的能源消耗平均增加了约10%至30%。结果比较模糊。 - Reuben Bond

2

Scala编译器将创建JVM字节码。因此,在较低层次上,它就像运行Java一样。因此,性能将与Java相当。

然而,Scala编译器如何创建字节码可能会对性能产生一些影响。我认为,由于Scala是新的,并且由于其字节码生成可能存在的低效,Scala在Android上会比Java慢一些,但差别不大。


我提供了事实。在这种情况下,衡量性能本身确实是一个猜测。从理论上讲,Java和Scala具有相同的字节码,因此它们可以达到相同的性能。但是,实际性能取决于程序员。一个好的Scala程序将比一个糟糕的Java程序更快。而且,正如@om-nom-nom所说的那样,相同的编程方法不适用于Java和Scala,他给出了一个很好的解释。 - Aneesh
所以,没有通用的答案来回答这个问题。Scala也不是新的,它已经出现了将近十年。它在低级别的字节码生成方面也不是问题所在。 - Dave Newton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接