New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inlining can prolong object lifetimes leading to OutOfMemoryError #9137
Comments
Imported From: https://issues.scala-lang.org/browse/SI-9137?orig=1 |
@lrytz said: for reference, adding links to Rex's suggestion of nulling out locals |
@retronym said: |
@retronym said: |
@lrytz should this stay open and assigned to you? |
yes, keep it open |
This should fix scala/bug#9137
This should fix scala/bug#9137
This should fix scala/bug#9137
There are two variants of this bug. In the first one, the inliner creates a new local variable (in the example below for the receiver): object Test {
def main(args: Array[String]): Unit =
new Stream().ident.next.next.next.next.next.next.next.next
class Stream() {
println("new Stream")
val data = Array.ofDim[Byte](256 * 1024 * 1024)
lazy val next = new Stream
@noinline def id(s: Stream) = s
@inline final def ident: Stream = id(this)
}
} This can be fixed by setting all local vars created by the inliner to object Test {
def main(args: Array[String]): Unit =
new Stream().ident.next.next.next.next.next.next.next.next
class Stream() {
println("new Stream")
val data = Array.ofDim[Byte](256 * 1024 * 1024)
lazy val next = new Stream
@inline final def ident: Stream = {
var alias: Stream = null
if (data != null) alias = this
alias
}
}
} To avoid a full combined liveness&nullness analysis, we can just set all those local vars to null after inlining a method (part of scala/scala#7133). |
This should fix scala/bug#9137
For reference, someone implemented liveness analysis for nulling out locals using ASM, it seems under BSD license https://github.com/levans/Open-Quark/blob/master/src/CAL_Platform/src/org/openquark/cal/internal/javamodel/NullingClassAdapter.java |
Not really related to inlining anymore, but something like this, either at bytecode or at Scala-language level, could also make the runtime semantics of block expressions more intuitive. val x = {
val tmp = getBigObject()
tmp.mutate(42)
processBigObject(tmp)
}
// tmp out of scope for Scala, but GC doesn't know it |
Yes, I'm not saying it's a useless optimization. But at least the user can manually make So I think it makes sense to be eager about nulling out locals in the inliner for now. |
This should fix scala/bug#9137
This should fix scala/bug#9137
This should fix scala/bug#9137
This should fix scala/bug#9137
This should fix scala/bug#9137
This should fix scala/bug#9137
Remove `@noinline` annotations from `LazyList` since scala/bug#9137 is fixed.
The text was updated successfully, but these errors were encountered: