猿问

与 Java 相比,Kotlin 中并发 shell 命令的性能较差

我有一个奇怪的问题,我发现运行并发 shell 命令以提取文件的 Kotlin 代码性能非常差。但是,当使用 Java 代码运行相同的 shell 命令时,性能符合预期。


差异非常显着,Java 代码运行时间为 10-20 秒,而 Kotlin 代码运行时间约为 13 分钟。


特定用例是一个产生 15 个线程的函数,所有线程都调用此提取函数来解压相同的 tar.gz 文件。调用Kotlin函数时,性能较差;当它是Java时,性能如预期。


我反编译为 Java 的 Kotlin 代码与性能良好的 Java 代码几乎相同,唯一的区别是添加了 Kotlin Intrinsics,这应该不会影响性能。


科特林代码:


@Synchronized

@Throws(IOException::class)

fun extractTar(tarFile: Path, extractPath: Path) {

    logger.info("Extracting file: " + tarFile.toString())

    logger.info("Destination path: " + extractPath.toString())

    val start = System.currentTimeMillis()

    val untarCommand = Arrays.asList("tar", "-xzf", tarFile.toString(), "-C", extractPath.toString())

    val untarProcess = ProcessBuilder()

            .command(untarCommand)

            .redirectErrorStream(true)

            .start()

    waitAndCheckProcessOutput(untarProcess, "tar -xzf ${tarFile.toString()} -C ${extractPath.toString()}", 15)


    logger.info("Running chmod on folder:" + extractPath.toString())

    val chmodCommand = Arrays.asList("chmod", "-R", "0777", extractPath.toString())

    val chmodProcess = ProcessBuilder()

            .command(chmodCommand)

            .redirectErrorStream(true)

            .start()

    waitAndCheckProcessOutput(chmodProcess, "chmod -R 0777 ${extractPath.toString()}", 15)


    logger.info("Extracted in " + printTime(System.currentTimeMillis() - start))

}

它是这样调用的:

IntStream.range(0, count).parallel().forEach{ unsynchronizedMethod() }

在此 unsynchronizedMethod 中调用 extractTar 的地方。

我 95% 确定在 Intrinsic 库调用中不会发生减速,因为检查的值都不应该为空。

还有趣的是,对于少量线程,例如2个线程不会发生减速。随着线程数的增加,性能下降,这让我怀疑这实际上是并发问题。

我还尝试运行 Kotlin-decompiled-to-Java 代码,去除 Intrinsic 库调用,并且该代码具有与本机 Java 代码相同的性能。


qq_花开花谢_0
浏览 374回答 1
1回答

慕容森

通过将提取物移入固定companion object {}不知道为什么这解决了问题,但确实如此
随时随地看视频慕课网APP

相关分类

Java
我要回答