Performance 功能性进近比Kotlin中的顺序进近慢100倍?
所以我又拿起了Euler项目和Kotlin玩了一会儿。对于那些不了解ProjectEuler的人来说,它是一个编程练习从平庸到相当困难的网站 无论如何,第一个问题是: 如果我们列出10以下的所有自然数,它们是3或5的倍数,我们得到3、5、6和9。这些倍数之和是23 求1000以下所有3或5的倍数之和 我从顺序和功能上解决了这个问题,因为我想看看它们之间的比较:Performance 功能性进近比Kotlin中的顺序进近慢100倍?,performance,kotlin,functional-programming,Performance,Kotlin,Functional Programming,所以我又拿起了Euler项目和Kotlin玩了一会儿。对于那些不了解ProjectEuler的人来说,它是一个编程练习从平庸到相当困难的网站 无论如何,第一个问题是: 如果我们列出10以下的所有自然数,它们是3或5的倍数,我们得到3、5、6和9。这些倍数之和是23 求1000以下所有3或5的倍数之和 我从顺序和功能上解决了这个问题,因为我想看看它们之间的比较: class ProjectEuler1 { companion object { fun sequential
class ProjectEuler1 {
companion object {
fun sequential(): Int {
var sum = 0
for (i in 1..999)
if (i % 3 == 0 || i % 5 == 0)
sum += i
return sum
}
fun functional(): Int = (1..999).filter { it % 3 == 0 || it % 5 == 0 } .sum()
fun benchmark() {
var solSequential = -1
val tSequential = measureExactTimeMillis { solSequential = sequential() }
var solFunctional = -1
val tFunctional = measureExactTimeMillis { solFunctional = functional() }
println("""
+---
|${this::class.java.canonicalName.replace(".Companion", "")}
+---
|Sequential solution: $solSequential
|Sequential running time: ${tSequential.round(6)} ms
+---
|Functional solution: $solFunctional
|Functional running time: ${tFunctional.round(6)} ms
+---
""".trimIndent())
}
}
}
measureExactTimeMillis
只是measureNanoTime
除以1\u 000
返回一个Double
无论如何,运行几次后,输出总是或多或少如下:
+---
|ProjectEuler1
+---
|Sequential solution: 233168
|Sequential running time: 0.6097 ms
+---
|Functional solution: 233168
|Functional running time: 33.3555 ms
+---
顺序版本比简单的功能实现快50-100倍,遗憾的是更详细
这是什么原因?性能是否至少应该具有可比性(相对于数量级的差异)?我错过了优化函数实现应该做的事情了吗?我猜测为什么函数版本会慢一些:装箱/取消装箱的原语和创建中间
列表@Slaw的组合我认为kotlin函数的编译类似于Java streams,Java streams可以在在每一步之后,背景是延迟计算,而不是急切的收集。为Iterable
提供的扩展函数是急切的,并返回中间Iterable。Java streams的Kotlin等价物,或至少接近等价物是。@Slaw我在几分钟前也发现了这一点,但在筛选器之前添加.asSequence()
,使操作花费的时间延长了10-20%。当然,这都是关于装箱/取消装箱和额外的集合。JVM对具有基元类型的操作进行了大量优化,而对装箱类型则没有。在顺序代码中,您只需使用primitiveint
作为迭代器,对
执行一个简单的循环,在“函数”代码中,您创建一个装箱的整数
的列表
,并使用迭代器对其进行迭代。序列可以帮助您避免额外的集合,但它们是通用的,因此装箱/取消装箱将保持不变。