我建立一個簡單的例子來檢查@inline標註行爲:製作方法其實內聯
import scala.annotation.tailrec
object InlineTest extends App {
@inline
private def corec(x : Int) : Int = rec(x - 1)
@tailrec
private def rec(x : Int) : Int =
if (x < 3) x else {
if (x % 3 == 0)
corec(x-1)
else
rec(x-4)
}
@tailrec
private def rec1(x : Int) : Int =
if (x < 3) x else {
if (x % 3 == 0) {
val arg = x - 1
rec1(arg - 1)
} else
rec1(x-4)
}
Console.println(rec(args(0).toInt))
}
這個例子編譯時沒有警告,無論tailrec註釋是有效,因爲我以爲。但是當我真的執行代碼時,它給了我一個stackoverflow異常。這意味着由於內聯方法沒有內聯,尾遞歸優化失敗。
我有從原來的不同之處僅手動地執行「內聯」變換控制功能rec1
。由於這個函數按預期運行良好,避免了使用尾遞歸的stackoverflow異常。
是什麼阻止註釋的方法被內聯?
我知道互相遞歸沒有被scala編譯器優化。所以我選擇它來檢查函數內聯。如果內聯工作,那麼遞歸將被優化,如果不起作用,那麼該方法將失敗,並帶有stackoverflow。此外,如果內聯註釋對優化JVM有任何益處,那麼這裏有幾個問題。我認爲內聯可能會打開進一步優化的大門,但事實上,我認爲這太多了。 – ayvango 2014-08-30 13:17:42