質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

3回答

4555閲覧

kotlinのインライン化のメリットが分かりません。

退会済みユーザー

退会済みユーザー

総合スコア0

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

1クリップ

投稿2017/05/28 21:08

Kotlin日本語和訳より、inline関数lock()は

lock(l) { foo() }

コンパイル後

l.lock() try { foo() } finally { l.unlock() }

のようにコンパイラに処理されるようです。
こうすることにより、実行時間を短くしているのは分かったのですが、
コンパイル後で、何が実行時間を短くしたか分かりません。
確かに、コードがインライン化され展開されていますが、関数の呼び出しコストが下がっているように思えません。

何が、実行コストを下げているを教えてください。お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

こちらの和訳から引用して説明します。

高階関数を使用すると、特定のランタイムペナルティを課せられます。各関数はオブジェクトであり、それはクロージャ、すなわち、関数の本体でアクセスされるそれらの変数をキャプチャします。メモリ割り当て(関数オブジェクトとクラス用の両方)と仮想呼び出しは、実行時のオーバーヘッドを招きます。

しかし、多くの場合、オーバーヘッドのこの種のラムダ式をインライン化することによって解消することができると思われます。

ということで、インライン化によって解消できるのはラムダ生成のコストであって、関数呼び出しのコストではありません。

投稿2017/05/28 22:18

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/05/29 06:58

質問を正してくださりありがとうございます。 今では、なぜ、ラムダ生成のコストがあるのか理解できました。 また、回答お願いします。
guest

0

ベストアンサー

理由の一つには「ローカル変数のアクセス効率化」があるのではないかと思い、byte codeを調べてみました。

次のようなコードを考えてみます。

kotlin

1... 2void foo(l: Lock) { 3 val a = ...; 4 lock(l) { 5 a += 1 6 foo(a) 7 } 8}

インライン展開されない場合、{ a += 1; foo(a) }の部分はラムダ式(?)となるだろうと思います。実装の話になりますが、ラムダ式はjavaで表現するとおおよそ次のようなものになるようです。

java

1import kotlin.jvm.internal.Ref.IntRef; 2import kotlin.jvm.functions.Function0; 3 4void foo(Lock l) { 5 IntRef _a = new IntRef(...); 6 lock(l, new $1(_a)); 7 8 // lambdaを表現する内部的なクラス 9 class $1 implements Function0 { 10 $1(IntRef _a) { 11 $a = _a; 12 } 13 14 Void invoke() { 15 $a.element += 1; 16 foo($a.element); 17 } 18 } 19}

javaと異なりKotlinではlambda内からアクセスすることのできるローカル変数はmutableでかまいません。ご存知のようにjavaのlambda/内部クラスでは外側のスコープにあるローカル変数はimmutableでなければならないという制限があります。(この点でもkotlinはbetter javaたらんとしています...っていうかC#やScalaでもできるのでKotlinができない訳にはいかないのかも知れません)

ただJVMはあるメソッドのスタックフレーム上にあるローカル変数をそのメソッド以外からアクセスするbyte codeをサポートしていないので、上記のように実装が幾分トリッキーなことになっています。

つまりインライン関数にしておかないと、ラムダ式から外側のローカル変数を更新するようなコードを実現するために、ローカル変数の内部実装がintではなくIntRefになり、lambdaのクロージャーの生成(new $1)に内部でアクセスするローカル変数を引き渡したりする余分なコードが増えてしまいます。
インライン関数にしておきさえすればこのようなオーバーヘッドを削減できますね。

以上がインライン化する目的の一つになっているように思います。

投稿2017/05/28 22:27

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/05/28 22:31

...と考えてみたのですが、そもそもlockってインライン関数じゃなかったのです? あらら?
maisumakun

2017/05/28 22:37 編集

すみません、少し寝ぼけたことを書いてしまったので、ここのコメントは上書きしておきます。
KSwordOfHaste

2017/05/28 22:43

いずれにせよinlineかどうか確認できてないままコメントしたのはよくなかったですね。 その点失礼しました。>みなさま
退会済みユーザー

退会済みユーザー

2017/05/29 06:56

具体例まで示してくださり大変納得いたしました。 ローカル変数のアクセス効率化は、この場合達成されていますね。 はやく、自分で理由を発見できるようにならなきゃいけないですね。 根拠の探し方も勉強になります。 ありがとうございました!!
guest

0

読み違いだと思います。

投稿2017/05/28 21:48

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/05/29 06:59

確かに、関数呼び出しのコストではなく、ラムダ生成のコストでしたね。 指摘をありがとうございます。 また、回答お願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問