You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I produce chunks of data with flow {} and then transform them into smaller parts as in the following example:
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
generate().flattenToBooleans().collect()
}
}
fun generate() = flow {
emit((1..99999).toMutableList())
delay(99999)
}
fun Flow<MutableList<Int>>.flattenToBooleans() = transform { list ->
list.forEach { emit(it == 99999) }
}
suspend fun Flow<Boolean>.collect() = collect { isLast ->
if (isLast) {
println("the last has been collected")
}
}
I expect the initial list of 99999 integers to be removed by the GC after it is transformed to booleans, but for some reason, it is still kept in the memory after "the last has been collected" is printed:
If I manually clear the list, the objects are removed and everything works normally:
// ...
fun Flow<MutableList<Int>>.flattenToBooleans() = transform { list ->
list.forEach { emit(it == 99999) }
list.clear()
}
// ...
If I send another list of integers in flow {}, the first one is expectedly removed from the heap, but the new one is still present somewhere in another place:
I expect the processed elements to be removed by the GC as soon as possible when using transform to free up the space for the other coroutines. This is the code example where commenting out list.clear() makes the program run out of the heap space with -Xmx500m:
fun main() {
runBlocking {
repeat(3) {
launch {
generate().flattenToBooleans().collect()
}
delay(500)
}
}
}
fun generate() = flow {
emit((1..9999999).toMutableList())
delay(99999)
}
fun Flow<MutableList<Int>>.flattenToBooleans() = transform { list ->
list.forEach { emit(it == 9999999) }
list.clear() // comment this line to make the code fail with -Xmx500m
}
suspend fun Flow<Boolean>.collect() = collect { isLast ->
if (isLast) {
println("last collected")
}
}
Kotlin 1.6.10, coroutines 1.6.0, azul-15.0.6 JVM on an ARM macOS.
The text was updated successfully, but these errors were encountered:
Kotlin#3199)
* Properly cleanup completion in SafeCollector to avoid unintended memory leak that regular coroutines (e.g. unsafe flow) are not prone to
Also, FieldWalker is improved to avoid "illegal reflective access"
FixesKotlin#3197
Co-authored-by: Roman Elizarov <elizarov@gmail.com>
I produce chunks of data with
flow {}
and then transform them into smaller parts as in the following example:I expect the initial list of 99999 integers to be removed by the GC after it is transformed to booleans, but for some reason, it is still kept in the memory after "the last has been collected" is printed:
If I manually clear the list, the objects are removed and everything works normally:
If I send another list of integers in
flow {}
, the first one is expectedly removed from the heap, but the new one is still present somewhere in another place:I expect the processed elements to be removed by the GC as soon as possible when using
transform
to free up the space for the other coroutines. This is the code example where commenting outlist.clear()
makes the program run out of the heap space with-Xmx500m
:Kotlin 1.6.10, coroutines 1.6.0, azul-15.0.6 JVM on an ARM macOS.
The text was updated successfully, but these errors were encountered: