簡單測試 Kotlin native 性能

準備

一直使用kotlin JVM平臺開發服務器的應用,最近想試試看 Kotlin native的性能。

我使用的是 kotlin native 1.3.21,要使用他非常的簡單,下載最新的 IDEA ,我下載的是 IntelliJ IDEA 2018.3.4 (Community Edition),然後新建項目時選擇 “Kotlin/Native”,非常的簡單了。

測試環境如下:

Windows 10 64 位

Intel Core i5-6500 @3.2GHz   4 Core

16GB RAM

測試代碼

這個項目還在初期,所以對應的庫一定還不成熟,所以,我盡力避免使用庫,而且不同的庫實現不同和使用不當,都可能造成測試不準確。

所以我測試簡單的循環,int的位操作,這些指令都是對編譯器的考驗,下面的測試代碼就是檢測一個int32值,包含幾個有效的 1 位。

package sample

//import kotlin.random.Random
import kotlin.system.measureNanoTime

fun main() {
    runIt()
}

private fun runIt(){
    var sum = 0
    val time = measureNanoTime{
        //val ran = Random.Default
        for (i in 0 until 1_0000_0000){
            //val v = ran.nextInt()
            sum += getInt32TrueCount(i)
        }
    }
    // 292 056 900
    println("共耗時:$time ns, result: $sum")
}

private fun getInt32TrueCount(value: Int):Int {
    if (value == 0) {
        return 0
    }

    return getByteTrueCount(value and 0xFF) +
            getByteTrueCount((value shr 8) and 0xFF) +
            getByteTrueCount((value shr 16) and 0xFF) +
            getByteTrueCount((value shr 24) and 0xFF)
}

private fun getByteTrueCount(value: Int) : Int{
    if(value== 0){
        return 0
    }

    val a = (value and 0x1)
    val b = ((value and 0x2)  shr 1)
    val c = ((value and 0x4)  shr 2)
    val d = ((value and 0x8)  shr 3)
    val e = ((value and 0x10) shr 4)
    val f = ((value and 0x20) shr 5)
    val g = ((value and 0x40) shr 6)
    val h = ((value and 0x80) shr 7)

    return a + b + c + d + e + f + g + h
}

測試結果

Kotlin有個非常大的好處,常見的庫都可以在 jvm 平臺和 native 平臺通用,所以上面的代碼可以直接複製到 Kotlin 的jvm環境下執行。

在 Gradle 面板中,找到 Tasks -> run -> runMainReleaseExecutableMingw,就可以運行程序。

耗時如下:

Kotlin Native :     292 056 900 ns

Kotlin Jvm    :1 220 617 300 ns

可以明顯看見,native是jvm的 4被性能,我在懷疑是不是 native 的LLVM編譯器 實現了並行,不然怎麼差不多4倍呢?

 坑

你可能注意到,我註釋了隨機數產生的函數調用,這是因爲我發現 native 平臺下,默認的隨機數產生非常的慢,遠遠慢於 Jvm 平臺。所以庫可能不太成熟。

 

SIMD

LLVM平臺的最大亮點是性能的優化,比如 SIMD,所以我嘗試修改程序,看看是否能啓用SIMD,所以我修改了函數,新代碼如下:

private val m1 = intArrayOf(0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80)

private fun getByteTrueCount(value : Int) : Int{
    if (value == 0) {
        return 0
    }

    var sum = 0
    for (i in 0 until m1.size){
        sum += (value and m1[i] shr i)
    }

    return sum
}

然而,悲劇發生了,執行時間如下:

Kotlin Native :   80 610 886 500 ns

Kotlin Jvm    :   1 297 672 800 ns

最終,native平臺花了整整80多秒,你沒有看錯, native慢了很多很多,而JVM平臺似乎能聰明的實現了SIMD優化(我猜的)。

至於爲什麼,我無法知道,

所以,還是比較多的坑。

 

後記

我提了一個 Issue 給了kotlin native,參見: https://github.com/JetBrains/kotlin-native/issues/2660

他們建議不要使用全局的數組,我修改了,效果不明顯。

另外,他們還建議使用 GCC的內置函數 __builtin_popcount

至於爲什麼 native 比 Jvm 平臺這段代碼要慢的原因,他們的意見是現在還是 beta 哪,不要做性能測試

雖然有一些問題,但是我任然非常期待 Kotlin native,這樣學會一個 kotlin ,就所有平臺通殺了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章