考虑一下:
import kotlin.system.measureTimeMillis
fun main() {
// Uncomment, and make it >=2 elements will make [timeInMillis] 0.
// Changing [setOf] to [arrayOf] doesn't help.
// setOf(1, 2)
val timeInMillis = measureTimeMillis {
3 in arrayOf(4)
}
println("$timeInMillis ms")
}
我相信 arrayOf(4) 中的 3
相当于 ArraysKt.contains(new Integer[]{4}, 3);
Java 代码。
出于某种原因,在 JVM 中的 Linux 上,timeInMillis
最多可能需要 30 毫秒。我在对 Android 上的同等产品进行基准测试时发现了这一点,在 Pixel 2 设备上,它可能需要长达 90 毫秒的时间。考虑到工作量,这些数字似乎相当大。
我的猜测是 Kotlin stdlib 中正在进行某种惰性初始化,从而导致了这种情况。我如何了解更多有关正在发生的事情?
最佳答案
My guess is that there's some sort of lazy initialization going on in Kotlin stdlib which causes this.
确实存在延迟初始化,这与 Kotlin 无关,而是与 JVM 有关。这就是 JVM 加载类的方式。您可以使用 -verbose:class
JVM 选项来找出哪些类已初始化。
println("Measure Start!")
val timeInMillis = measureNanoTime {
3 in arrayOf(4)
}
println("Measure End!")
println("$timeInMillis ns")
在我的 macOS 机器上使用 IntelliJ 运行此命令并使用 -verbose:class
打印(仅显示输出的相关部分):
Measure Start!
[0.132s][info][class,load] java.net.SocketAddress source: jrt:/java.base
[0.132s][info][class,load] java.net.InetSocketAddress source: jrt:/java.base
[0.132s][info][class,load] java.net.InetAddress source: shared objects file
[0.133s][info][class,load] jdk.internal.access.JavaNetInetAddressAccess source: shared objects file
[0.133s][info][class,load] java.net.InetAddress$1 source: shared objects file
[0.133s][info][class,load] java.net.InetAddress$InetAddressHolder source: shared objects file
[0.133s][info][class,load] java.util.SortedSet source: shared objects file
[0.133s][info][class,load] java.util.NavigableSet source: shared objects file
[0.133s][info][class,load] java.util.concurrent.ConcurrentSkipListSet source: shared objects file
[0.134s][info][class,load] java.util.SortedMap source: shared objects file
[0.134s][info][class,load] java.util.NavigableMap source: shared objects file
[0.134s][info][class,load] java.util.concurrent.ConcurrentNavigableMap source: shared objects file
[0.134s][info][class,load] java.util.concurrent.ConcurrentSkipListMap source: shared objects file
[0.134s][info][class,load] java.util.concurrent.ConcurrentSkipListMap$Index source: shared objects file
[0.134s][info][class,load] java.util.concurrent.atomic.Striped64 source: shared objects file
[0.134s][info][class,load] java.util.concurrent.atomic.LongAdder source: shared objects file
[0.134s][info][class,load] java.util.concurrent.ConcurrentSkipListMap$Node source: shared objects file
[0.134s][info][class,load] java.net.InetAddressImplFactory source: shared objects file
[0.134s][info][class,load] java.net.InetAddressImpl source: shared objects file
[0.134s][info][class,load] java.net.Inet6AddressImpl source: shared objects file
[0.134s][info][class,load] java.lang.Class$1 source: shared objects file
[0.135s][info][class,load] java.net.InetAddress$NameService source: shared objects file
[0.135s][info][class,load] java.net.InetAddress$PlatformNameService source: shared objects file
[0.135s][info][class,load] java.net.Inet4Address source: shared objects file
[0.135s][info][class,load] java.net.InetSocketAddress$InetSocketAddressHolder source: jrt:/java.base
[0.135s][info][class,load] java.net.SocketOptions source: jrt:/java.base
[0.135s][info][class,load] java.net.SocketImpl source: jrt:/java.base
[0.136s][info][class,load] java.net.SocketImpl$$Lambda$14/0x0000000800b69840 source: java.net.SocketImpl
[0.136s][info][class,load] sun.net.NetProperties source: jrt:/java.base
[0.136s][info][class,load] sun.net.NetProperties$1 source: jrt:/java.base
[0.136s][info][class,load] java.util.Properties$LineReader source: shared objects file
[0.137s][info][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.138s][info][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.138s][info][class,load] sun.nio.ch.NativeDispatcher source: jrt:/java.base
[0.138s][info][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
[0.138s][info][class,load] sun.nio.ch.IOUtil source: jrt:/java.base
[0.140s][info][class,load] java.util.concurrent.locks.AbstractQueuedSynchronizer source: shared objects file
[0.140s][info][class,load] java.util.concurrent.locks.ReentrantLock$Sync source: shared objects file
[0.140s][info][class,load] java.util.concurrent.locks.ReentrantLock$NonfairSync source: shared objects file
[0.140s][info][class,load] java.net.SocksConsts source: jrt:/java.base
[0.140s][info][class,load] java.net.DelegatingSocketImpl source: jrt:/java.base
[0.140s][info][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.140s][info][class,load] sun.nio.ch.Net source: jrt:/java.base
[0.140s][info][class,load] java.net.ProtocolFamily source: jrt:/java.base
[0.140s][info][class,load] sun.nio.ch.Net$1 source: jrt:/java.base
[0.141s][info][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.141s][info][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.141s][info][class,load] java.net.SocketOption source: jrt:/java.base
[0.141s][info][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.141s][info][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.141s][info][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.141s][info][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.141s][info][class,load] jdk.net.MacOSXSocketOptions source: jrt:/jdk.net
[0.143s][info][class,load] kotlin.collections.ArraysKt__ArraysJVMKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.143s][info][class,load] kotlin.collections.ArraysKt__ArraysKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.143s][info][class,load] kotlin.collections.ArraysKt___ArraysJvmKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.143s][info][class,load] kotlin.collections.ArraysKt___ArraysKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.143s][info][class,load] kotlin.collections.ArraysKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.143s][info][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.144s][info][class,load] java.net.Inet6Address source: shared objects file
[0.145s][info][class,load] java.net.Inet6Address$Inet6AddressHolder source: shared objects file
[0.151s][info][class,load] kotlin.jvm.internal.Intrinsics source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.151s][info][class,load] kotlin.KotlinNullPointerException source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.152s][info][class,load] kotlin.UninitializedPropertyAccessException source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.152s][info][class,load] java.lang.AssertionError source: jrt:/java.base
[0.152s][info][class,load] java.lang.IllegalStateException source: jrt:/java.base
[0.152s][info][class,load] java.lang.UnsupportedOperationException source: jrt:/java.base
[0.152s][info][class,load] java.net.StandardProtocolFamily source: jrt:/java.base
Measure End!
20704379 ns
记下时间戳。
当您在 arrayOf(4) 中执行 3
时,加载了很多类,因为这是您第一次使用这些类。请特别注意 kotlin.collections.ArraysKt
已加载。
如果你先这样做怎么办?
println("Calling setOf")
println(setOf(1, 2))
输出变为:
Calling setOf
[0.126s][info][class,load] jdk.internal.access.JavaNetInetAddressAccess source: shared objects file
[0.126s][info][class,load] java.net.InetAddress$1 source: shared objects file
[0.126s][info][class,load] java.net.InetAddress$InetAddressHolder source: shared objects file
[0.126s][info][class,load] java.util.SortedSet source: shared objects file
[0.126s][info][class,load] java.util.NavigableSet source: shared objects file
[0.126s][info][class,load] java.util.concurrent.ConcurrentSkipListSet source: shared objects file
[0.126s][info][class,load] java.util.SortedMap source: shared objects file
[0.126s][info][class,load] java.util.NavigableMap source: shared objects file
[0.126s][info][class,load] java.util.concurrent.ConcurrentNavigableMap source: shared objects file
[0.126s][info][class,load] java.util.concurrent.ConcurrentSkipListMap source: shared objects file
[0.126s][info][class,load] java.util.concurrent.ConcurrentSkipListMap$Index source: shared objects file
[0.126s][info][class,load] java.util.concurrent.atomic.Striped64 source: shared objects file
[0.126s][info][class,load] java.util.concurrent.atomic.LongAdder source: shared objects file
[0.126s][info][class,load] java.util.concurrent.ConcurrentSkipListMap$Node source: shared objects file
[0.126s][info][class,load] java.net.InetAddressImplFactory source: shared objects file
[0.127s][info][class,load] java.net.InetAddressImpl source: shared objects file
[0.127s][info][class,load] java.net.Inet6AddressImpl source: shared objects file
[0.127s][info][class,load] kotlin.collections.SetsKt__SetsJVMKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.127s][info][class,load] kotlin.collections.SetsKt__SetsKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.127s][info][class,load] java.lang.Class$1 source: shared objects file
[0.127s][info][class,load] kotlin.collections.SetsKt___SetsKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.127s][info][class,load] kotlin.collections.SetsKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.127s][info][class,load] java.net.InetAddress$NameService source: shared objects file
[0.127s][info][class,load] java.net.InetAddress$PlatformNameService source: shared objects file
[0.127s][info][class,load] java.net.Inet4Address source: shared objects file
[0.127s][info][class,load] java.net.InetSocketAddress$InetSocketAddressHolder source: jrt:/java.base
[0.128s][info][class,load] java.net.SocketOptions source: jrt:/java.base
[0.128s][info][class,load] java.net.SocketImpl source: jrt:/java.base
[0.128s][info][class,load] kotlin.jvm.internal.Intrinsics source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.128s][info][class,load] java.net.SocketImpl$$Lambda$14/0x0000000800b6a040 source: java.net.SocketImpl
[0.128s][info][class,load] kotlin.KotlinNullPointerException source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.129s][info][class,load] sun.net.NetProperties source: jrt:/java.base
[0.129s][info][class,load] sun.net.NetProperties$1 source: jrt:/java.base
[0.129s][info][class,load] java.util.Properties$LineReader source: shared objects file
[0.129s][info][class,load] kotlin.UninitializedPropertyAccessException source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.129s][info][class,load] java.lang.AssertionError source: jrt:/java.base
[0.129s][info][class,load] java.lang.IllegalStateException source: jrt:/java.base
[0.129s][info][class,load] java.lang.UnsupportedOperationException source: jrt:/java.base
[0.130s][info][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.130s][info][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.130s][info][class,load] sun.nio.ch.NativeDispatcher source: jrt:/java.base
[0.130s][info][class,load] sun.nio.ch.SocketDispatcher source: jrt:/java.base
[0.130s][info][class,load] sun.nio.ch.IOUtil source: jrt:/java.base
[0.132s][info][class,load] java.util.concurrent.locks.AbstractQueuedSynchronizer source: shared objects file
[0.132s][info][class,load] java.util.concurrent.locks.ReentrantLock$Sync source: shared objects file
[0.132s][info][class,load] java.util.concurrent.locks.ReentrantLock$NonfairSync source: shared objects file
[0.132s][info][class,load] java.net.SocksConsts source: jrt:/java.base
[0.132s][info][class,load] java.net.DelegatingSocketImpl source: jrt:/java.base
[0.132s][info][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.133s][info][class,load] sun.nio.ch.Net source: jrt:/java.base
[0.133s][info][class,load] java.net.ProtocolFamily source: jrt:/java.base
[0.133s][info][class,load] sun.nio.ch.Net$1 source: jrt:/java.base
[0.133s][info][class,load] sun.net.ext.ExtendedSocketOptions source: jrt:/java.base
[0.133s][info][class,load] jdk.net.ExtendedSocketOptions source: jrt:/jdk.net
[0.133s][info][class,load] java.net.SocketOption source: jrt:/java.base
[0.133s][info][class,load] jdk.net.ExtendedSocketOptions$ExtSocketOption source: jrt:/jdk.net
[0.133s][info][class,load] jdk.net.SocketFlow source: jrt:/jdk.net
[0.133s][info][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions source: jrt:/jdk.net
[0.133s][info][class,load] jdk.net.ExtendedSocketOptions$PlatformSocketOptions$1 source: jrt:/jdk.net
[0.133s][info][class,load] jdk.net.MacOSXSocketOptions source: jrt:/jdk.net
[0.135s][info][class,load] jdk.net.ExtendedSocketOptions$1 source: jrt:/jdk.net
[0.136s][info][class,load] java.net.Inet6Address source: shared objects file
[0.136s][info][class,load] java.net.Inet6Address$Inet6AddressHolder source: shared objects file
[0.139s][info][class,load] kotlin.collections.ArraysKt__ArraysJVMKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.139s][info][class,load] kotlin.collections.ArraysKt__ArraysKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.139s][info][class,load] kotlin.collections.ArraysKt___ArraysJvmKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.139s][info][class,load] kotlin.collections.ArraysKt___ArraysKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.139s][info][class,load] kotlin.collections.ArraysKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.143s][info][class,load] java.net.StandardProtocolFamily source: jrt:/java.base
[0.146s][info][class,load] sun.nio.ch.NioSocketImpl$$Lambda$15/0x0000000800b6a440 source: sun.nio.ch.NioSocketImpl
[0.146s][info][class,load] java.net.SocksSocketImpl$3 source: jrt:/java.base
[0.146s][info][class,load] java.net.ProxySelector source: jrt:/java.base
[0.146s][info][class,load] sun.net.spi.DefaultProxySelector source: jrt:/java.base
[0.146s][info][class,load] java.net.Proxy source: jrt:/java.base
[0.147s][info][class,load] java.net.Proxy$Type source: jrt:/java.base
[0.147s][info][class,load] sun.net.spi.DefaultProxySelector$1 source: jrt:/java.base
[0.147s][info][class,load] sun.net.spi.DefaultProxySelector$NonProxyInfo source: jrt:/java.base
[0.147s][info][class,load] sun.net.spi.DefaultProxySelector$3 source: jrt:/java.base
[0.147s][info][class,load] sun.net.NetHooks source: jrt:/java.base
[0.147s][info][class,load] sun.net.NetHooks$Provider source: jrt:/java.base
[0.147s][info][class,load] sun.net.sdp.SdpProvider source: jrt:/java.base
[0.148s][info][class,load] sun.nio.ch.NativeThread source: jrt:/java.base
[0.150s][info][class,load] kotlin.collections.MapsKt__MapWithDefaultKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.150s][info][class,load] kotlin.collections.MapsKt__MapsJVMKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.150s][info][class,load] kotlin.collections.MapsKt__MapsKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.150s][info][class,load] kotlin.collections.MapsKt___MapsKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.150s][info][class,load] kotlin.collections.MapsKt source: file:/Applications/IntelliJ%20IDEA%20CE.app/Contents/plugins/Kotlin/kotlinc/lib/kotlin-stdlib.jar
[0.150s][info][class,load] java.util.LinkedHashMap$LinkedKeySet source: jrt:/java.base
[0.151s][info][class,load] java.util.LinkedHashMap$LinkedHashIterator source: shared objects file
[0.151s][info][class,load] java.util.LinkedHashMap$LinkedKeyIterator source: jrt:/java.base
[1, 2]
Measure Start!
Measure End!
19515 ns
正如您所看到的,现在所有类加载都在开始测量之前完成。具体来说,kotlin.collections.ArraysKt
也已在此处加载(0.139 秒)。
但是,如果您首先调用 arrayOf
而不是 setOf
,则它不会有效地工作,因为 arrayOf
是 内联
。 Kotlin 编译器直接将 arrayOf(1, 2)
翻译为 new Integer[] { 1, 2 }
,它不使用 ArraysKt
中的任何内容>,因此它不会导致 ArraysKt
被加载。
如果您使用一个元素调用 setOf
,则会发生类似的情况。单个参数 setOf
调用 java.util.Collections.singleton
,因此它不会使用 ArraysKt
中的任何内容:(
您还可以尝试使用 JVM 选项 -XX:+PrintCompilation
。它向您显示每个方法何时进行 JIT 编译。 JIT 编译方法所需的时间也可能是第一次调用 in
速度慢的原因。
关于kotlin - 第一次调用 `ArraysKt.contains` 很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68798954/