Hello and Happy New Year ! We stumble upon a perfo...
# server
t
Hello and Happy New Year ! We stumble upon a performance issue on
take()
. We introduce
tak()
to compare, which uses subList:
Copy code
fun <T> List<T>.tak(n: Int): List<T> = this.subList(0, min(this.size, n))
And here are the results :
Copy code
import io.biznet.commons.utils.tak
println("take");println("\n");println(java.util.Date().toInstant());println("\n");(1..1000000000).forEach { listOf("1","2","3","4").take(3) };println(java.util.Date().toInstant());println("\n");
println("tak");println("\n");println(java.util.Date().toInstant());println("\n");(1..1000000000).forEach { listOf("1","2","3","4").tak(3) };println(java.util.Date().toInstant());println("\n");
take
2024-01-04T22:38:17.654Z
2024-01-04T22:38:37.548Z
tak
2024-01-04T22:38:37.548Z
2024-01-04T22:38:38.515Z
Do we know why it is implemented this way ? Is it because it handles every Iterable and so can no rely on indexes ?
I wonder if sublist does not return a new list, which take does
c
I'm not sure you're measuring what you think you're measuring. These are very small lists, the noise is going to be large. Consider using kotlinx-benchmark or something similar.
But yes, it is expected that subList doesn't create a copy.
Do we know why it is implemented this way ?
As cited in the documentation above:
Structural changes in the base list make the behavior of the view undefined.
Also, not directly written here but it has been a concern elsewhere in the standard library: a view refers to the original list, so it cannot be GC'd. For example, if you have a list of billions of elements, and you call
subList(5, 7)
, although you are only using two elements, the entire list must stay in memory. With a copy, this is not the case, and all other elements can be freed. You can read more about the exact same problem for strings: https://bugs.java.com/bugdatabase/view_bug?bug_id=4513622
t
thanks a lot I'll read all this later today