在优化Scala代码时首先要查看哪里?
我目前需要优化一个太慢的算法的Scala实现.它以功能方式实现,仅使用值(val)和不可变数据结构.我已经记录了重要功能(所以我的代码中有一些可变地图),这使得我的代码的速度快了两倍,我不知道下一步该怎么做.
所以,我不是在寻求有关软件优化的通用建议(例如,首先优化您的algortihm,使用分析器,做基准测试…),而不是Scala特定或JVM特定的优化建议. 因此,在尝试优化Scala代码时,我的问题是哪里首先看?通常会导致放缓的常见语言结构或模式是什么? 特别是,我正在寻求以下几点建议: >我读取(…)结构缓慢,因为每次执行循环体时都会生成一个匿名类.是真的吗是否有任何其他地方生成匿名类? (例如,当使用map()和匿名函数时) 解决方法
过去我也不得不优化大量的Scala代码.以下不是一个完整的列表,只是一些可能有助于您的实际观察:
>是的,即使使用Scala 2.10,将for循环更换一段时间也会更快.有关详细信息,请参阅linked talk in the comments.此外,请注意,使用“过滤”(您正在迭代的收集之后的条件)将导致您的条件的盒子/拆箱,这可能对性能有很大的影响(see this post for details). ColtBitVector min: 0.042 avg: 0.245 max: 40.120 JavaBitSet min: 0.043 avg: 0.165 max: 4.306 JavaHashSet min: 0.191 avg: 0.716 max: 12.624 JavaTreeSet min: 0.313 avg: 1.428 max: 64.504 ScalaBitSetImmutable min: 0.380 avg: 1.675 max: 13.838 ScalaBitSetMutable min: 0.423 avg: 3.693 max: 457.146 ScalaSetImmutable min: 0.458 avg: 2.305 max: 9.998 ScalaSetMutable min: 0.340 avg: 1.332 max: 10.974 目前的问题是计算一个简单的整数集合(具有非常特定的大小和集合数).我想演示的是:选择正确/错误的收藏可以产生重大影响!再次,我认为很难给出这些数据类型中的哪一种选择的一般建议,因为这仅仅告诉我们在这个特殊的交叉问题中的性能(但是在替代方案中我选择了Java的HashSet).另外请注意,此交叉问题不需要可变数据类型.尽管如此,即使在不可变的功能中也可能会出现性能差异(而关于Set是可变集合明显更快,它是BitSet中不可变的集合).因此,根据情况,您可能希望选择不可变的集合,以获得最大性能(谨慎使用).>我被告知,声明一个变量private [this] var foo = …阻止创建getter / setter函数,应该更快(免责声明:我从未在微基准中确认).>当处理泛型类型时,为特定类型定义@specialized版本会导致加速.>尽管我尽量避免泛化,但我可以使用以下内容:尝试使用本地数组.在我的许多基准测试中,我刚刚结束了使用Arrays,考虑到它们在JVM中的实现,这是有道理的.>我想到的一个小点:我观察到使用companion对象(即SomeCollectionName(origCollection:_ *))在手工构造和构造中通过origCollection.toSomeCollectionName构造集合的差异.在许多情况下,后者明显更快. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |