我认为JMH 在这里可能很有用。您可以运行类似于下面的基准测试并尝试找出您的瓶颈。
请注意,这是在 Mode.SingleShotTime 中,因此模拟了 JIT 几乎没有机会做这件事的场景。
import org.openjdk.jmh.annotations.*
import java.util.concurrent.TimeUnit
import kotlin.random.Random
//@BenchmarkMode(Mode.AverageTime)
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
open class SplitToInt {
val count = 2 * 1_000_000
lateinit var stringToParse: String
lateinit var tokensToParse: List<String>
@Setup(Level.Invocation)
fun setup() {
stringToParse = (0..count).map { Random.nextInt(0, 100) }.joinToString(separator = " ")
tokensToParse = (0..count).map { Random.nextInt(0, 100) }.map { it.toString() }
}
@Benchmark
open fun split() =
stringToParse.split(" ")
@Benchmark
open fun map_toInt() =
tokensToParse.map { it.toInt() }
@Benchmark
open fun split_map_toInt() =
stringToParse.split(" ").map { it.toInt() }
}
我机器上的统计数据是:
Benchmark Mode Cnt Score Error Units
SplitToInt.map_toInt ss 48.666 ms/op
SplitToInt.split ss 124.899 ms/op
SplitToInt.split_map_toInt ss 186.981 ms/op
因此,拆分字符串并映射到 Ints 列表大约需要 187 毫秒。允许 JIT 预热 (Mode.AverageTime) 给我:
Benchmark Mode Cnt Score Error Units
SplitToInt.map_toInt avgt 5 30.670 ± 6.979 ms/op
SplitToInt.split avgt 5 108.989 ± 23.569 ms/op
SplitToInt.split_map_toInt avgt 5 120.628 ± 27.052 ms/op
这是快还是慢取决于具体情况,但您确定这里的输入转换是您获得 TLE 的原因吗?
编辑:如果您确实认为split(" ").map{ str -> str.toInt() } 太慢,您可以通过拆分将创建两个列表(一个来自split,一个来自map)替换为一个列表并一口气转型。我写了一个快速破解kotlin.text.Regex.split,它可以做到这一点,而且速度提高了大约 20%。
如果在您的用例中您只需要检查输入的一部分,splitToSequence 可能是更好的选择。