Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin/NativeのiOSにおけるオーバーヘッド

 Kotlin/NativeのiOSにおけるオーバーヘッド

マイクロベンチマークを用いてKotlin/NativeのiOSにおけるオーバーヘッドを測定していきます。
(指摘があったので注釈)
測定はデバッグビルドで行いました。スプレッドシートにはリリースビルドでの結果も後日反映いたします。

Takaki Hoshikawa

March 27, 2019
Tweet

More Decks by Takaki Hoshikawa

Other Decks in Technology

Transcript

  1. Kotlin/Nativeの
    iOSにおけるオーバーヘッド
    エムスリー株式会社 星川貴樹
    @どこでもKotlin #7

    View Slide

  2. Profile
    - 星川貴樹 (@oboenikui)
    - エムスリー株式会社所属 (2017〜)
    - Androidエンジニア
    - この勉強会の運営やってます

    View Slide

  3. Contents
    - マイクロベンチマークの実行結果とその考察
    - 相互運用におけるオーバーヘッド
    - ツール紹介
    - まとめ

    View Slide

  4. ベンチマーク

    View Slide

  5. マイクロベンチマークについて
    - Swift, Kotlin/Nativeで同等の処理を書き、iOS端末 (第5世代
    iPad)上で実行
    - ベンチマークの測定側のコードも各言語で実装
    - ベンチマークに用いるコードは、以下の記事のものを一部
    Kotlin/Native用に改変したものを使用
    Kotlin's hidden costs - Benchmarks
    - SingleShotTime (一定回数回すのにかかる時間) で測定
    https://github.com/oboenikui/kotlin-ios-benchmarks

    View Slide

  6. お詫び
    - Xcodeを昨日アップデートしたら (?) ベンチマークプロジェクトの
    ビルドが通らなくなったので確認中です
    - Xcodeに精通しているiOSエンジニアの方いらっしゃったら懇親会で
    こっそり話しかけてください

    View Slide

  7. 諸注意
    - ベンチマーク結果は2019/03/27現在の最新バージョンによるもの
    - 今後最適化が進み速くなる可能性は十分あります
    - マイクロベンチマークの結果は鵜呑みにしすぎないで
    - for文など、ボトルネックとなる部分が別に存在する可能性も
    - 特徴的な結果のみピックアップ
    - 全ての結果はこちらに

    View Slide

  8. ラムダ式 (クロージャ) の比較
    inlineの有無についても比較
    // no inline
    fun transaction(db: DB, body: ((DB) -> Int)): Int {
    db.beginTransaction()
    return try {
    val result = body(db)
    db.setTransactionSuccessful()
    result
    } finally {
    db.endTransaction()
    }
    }
    Kotlinコード Swiftコード

    View Slide

  9. ラムダ式 (クロージャ) の比較
    inlineの有無についても比較
    // inline
    inline fun inlineTransaction(db: DB, body: ((DB) -> Int)): Int {
    db.beginTransaction()
    return try {
    val result = body(db)
    db.setTransactionSuccessful()
    result
    } finally {
    db.endTransaction()
    }
    }
    Kotlinコード Swiftコード

    View Slide

  10. ラムダ式 (クロージャ) の比較結果
    - Kotlin/Nativeのラムダ式は現状遅い
    - inline化できる場合はSwiftと謙遜ない
    - (同様にローカル関数も遅い)
    no inline (ops/ms) inline (ops/ms)
    Swift 14,517 18,912
    Kotlin 3,005 16,985

    View Slide

  11. in (contains) の比較
    IntおよびStringのRange内存在判定を比較
    // 1..10 (local)
    fun isInOneToTenWithLocalRange(i: Int) = i in 1..10
    // 1..10 (indirect)
    private val myRange get() = 1..10
    fun isInOneToTenWithIndirectRange(i: Int) = i in myRange

    View Slide

  12. in (contains) の比較
    IntおよびStringのRange内存在判定を比較
    // Alfred..Alicia (local)
    fun isBetweenNamesWithLocalRange(name: String) = name in "Alfred".."Alicia"
    // Alfred..Alicia (constant)
    private val NAMES = "Alfred".."Alicia"
    fun isBetweenNamesWithLocalRange(name: String) = name in NAMES

    View Slide

  13. in (contains) の比較結果
    - Kotlinは大体が遅い(おそらく最適化されていない)
    - containsを使う場合は定数化することが望ましそう
    1..10
    (local) (indirect)
    Alfred..Alicia
    (local) (constant)
    Swift 33,291 32,639 2,570 24,078
    Kotlin 3,728 3,213 3,034 6,655

    View Slide

  14. forEachの比較
    RangeのforEachをforEachメソッド、for文で比較
    // method
    (1..10).forEach {
    blackHole.consume(it)
    }

    View Slide

  15. forEachの比較
    RangeのforEachをforEachメソッド、for文で比較
    // loop
    for (it in 1..10) {
    blackHole.consume(it)
    }

    View Slide

  16. forEachの比較
    RangeのforEachをforEachメソッド、for文で比較
    // loop w/ step
    for (it in 1..10 step 1) {
    blackHole.consume(it)
    }

    View Slide

  17. forEachの比較結果
    - Kotlinの方が圧倒的に速い!??
    - BlackHoleの実装で差が出た? → 後述
    method loop loop w/ step
    Swift 198 1,660 416
    Kotlin 474 3,405 3,441

    View Slide

  18. ツール紹介

    View Slide

  19. AppCode (EAP)
    - 言わずと知れたSwift, Objective-Cを快適に書けるIDE
    - Kotlin/NativeプラグインもEAP版に提供中
    - MPPを簡単に始められる!
    - stdlibのメソッドとかエラーになるのですが、そうならないノウハ
    ウをお持ちの方懇親会で教えてください!

    View Slide

  20. Hopper Disassembler
    - Intel, ARM, PowerPC向けバイナリの逆アセンブルツール
    - 個人ライセンスは ¥11,272 (時価)、無償トライアル版あり
    - アイコンがXcodeっぽいけど多分無関係
    - C-likeな擬似コードに逆コンパイルする機能があるので、自分のよ
    うなアセンブリ読みたくないマンにも優しい
    - Kotlin/Native関連のバグ調査に使えそう

    View Slide

  21. Hopper Disassembler
    Control Flow Graph
    (tutorialより引用)

    View Slide

  22. Hopper Disassembler
    Pseudo-Code
    (tutorialより引用)

    View Slide

  23. 相互運用のオーバーヘッド

    View Slide

  24. SwiftからKotlinを呼ぶコード

    View Slide

  25. SwiftからKotlinを呼ぶコード
    本来ここでコードとベンチマークを貼る予定だったのですが、Xcode
    アップデートでビルド & 実行ができなくなってしまいました
    とにかく何が言いたかったかと言うと……

    View Slide

  26. SwiftからKotlinを呼ぶコード
    遅い!!!!
    !!!!!!!!
    (Swiftのクラス初期化が4,000 ops/msに対して
    Kotlinのクラスは1,400 ops/msくらいだった気がする)

    View Slide

  27. SwiftからKotlinを呼ぶコードを調べてみる
    アセンブリアレルギーでもHopperを使って簡単に辿れることを実演しま

    View Slide

  28. まとめ
    - Kotlin/Native内で完結する処理は割と高速に動く
    - 現状速度を気にする場合は相互運用のコードに注意が必要
    - Hopper便利

    View Slide