Compiller works VERY slow for big amout of inlined code


#1

Here is synthetic sample:

class AA( @JvmField val name:String )

/** Inline form of [joinToString]*/
inline fun <T> Iterable<T>.join(separator : CharSequence = ", ", transform : (T) -> CharSequence) : String =
  joinItems(iterator(), StringBuilder(), separator, transform).toString()

/** Inline form of [joinTo]*/
inline fun <T, A : Appendable> joinItems(ar:Iterator<T>, buffer : A, separator : CharSequence = ", ", transform : (T) -> CharSequence) : A {
  buffer.append()
  var count = 0
  for (element in ar) {
    if (++count > 1) buffer.append(separator)
    buffer.append(transform(element))
  }
  return buffer
}

fun main(args : Array<String>) {
  val ar = arrayListOf( AA("1"), AA("2") )
  
  ar.join { it.name }
... // 500 similar lines
  ar.join { it.name }
}

I dont know how long its takes to compile this code, but after 20 minutes (!) compiller still do something and I kill process.

Is this problem of some kind or known future?


#2

It probably is a bug. Looking at what happens it is probably something to do with allocation of local slots. It should however not keep trying this long. In this example inlining is a bad thing to do as quite some nontrivial stuff happens in joinItems and even in join. You are absolutely blowing up the code size without real reason to do so.The JVM is quite efficient in doing these things for you if it is the right thing to do.


#3

I get this problem in absolutelly synthetic test: I was trying to reach code limit for single method and see how Kotling will handle this.
The actual code has no reason and must not. It just illustates some problems in code generation which lead to expotentially slower processing with increasing code size (or inlined count or something else).

Its not a big deal and rerelly affects in real life (I think) but it must be known and fixed in future.
The reason to fix this is here:

fun F() {
  val v = ""
  v.trim { it == ' ' }
//+ 580 lines of "v.trim { it == ' ' }"
}

This code compiled in 7 seconds and produce expected:

Error:Kotlin: [Internal Error] java.lang.RuntimeException: Error generating class file jm/test/ktest/KMainKt.class (compiled from [D:\java\myjava\kTest\src\kMain.kt]): Method code too large!

What the difference with my first example, which takes so much time to compile?


#4

Thanks for the report! Even if the case is synthetic it isn’t normal that the compiler silently dies for 20 minutes. I’ve created the issue issue KT-16470 in our bug tracker. If you’re interested in tracking progress, you can create an account at youtrack.jetbrains.com and vote for the issue at the issue page.