为什么 Kotlin 提交比 Java 慢得多?

Roh*_*rma 3 java kotlin

我对 Kotlin 很陌生。所以为了练习,我尝试用它来解决 LeetCode 中的问题。这是我今天解决的一个问题:
Distinct Subsequence(Leetcode)
首先我尝试用 Java 解决这个问题:

class Solution {
    public int numDistinct(String s, String t) {
        int[][] dp = new int[t.length() + 1][s.length() + 1];
        for (int i = 0; i <= s.length(); i++) {
            dp[0][i] = 1;
        }
        for (int i = 1; i <= t.length(); i++) {
            for (int j = 1; j <= s.length(); j++) {
                if (t.charAt(i - 1) != s.charAt(j - 1)) {
                    dp[i][j] = dp[i][j - 1];
                } else {
                    dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
                }
            }
        }
        return dp[t.length()][s.length()];
    }
}
Run Code Online (Sandbox Code Playgroud)

这是该算法的运行时间:

Runtime: 6 ms
Memory Usage: 39.4 MB
Run Code Online (Sandbox Code Playgroud)

然后我尝试在 Kotlin 中解决这个问题(下面的代码):

class Solution {
    fun numDistinct(s: String, t: String): Int {
        var dp = Array(t.count() + 1) {Array(s.count() + 1) {0} }
        for (i in 0 until s.count()) {
            dp[0][i] = 1;
        }
        for (i in 1..t.count()) {
            for (j in 1..s.count()) {
                if (t[i - 1] != s[j - 1]) {
                    dp[i][j] = dp[i][j - 1];
                } else {
                    dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
                }
            }
        }
        return dp[t.count()][s.count()]
    }
}
Run Code Online (Sandbox Code Playgroud)

令人震惊的是,上述 Kotlin 实现的算法的运行时间如下:

Runtime: 176 ms
Memory Usage: 34.2 MB
Run Code Online (Sandbox Code Playgroud)

问题是,与 Java 相比,为什么 Kotlin 解决方案的运行时间如此之长?

Ale*_*nov 6

翻译int[][]成 Kotlin 是Array<IntArray>; 你有,Array<Array<Int>>而不是对应Integer[][]于Java。所以你的 Kotlin 代码做了很多 Java 没有的装箱和拆箱。有关更多详细信息,请参阅https://kotlinlang.org/docs/reference/java-interop.html#java-arrays

Array(t.count() + 1) {IntArray(s.count() + 1) }
Run Code Online (Sandbox Code Playgroud)

至少应该解决这个问题(不指定 lambda 会将所有元素初始化为0)。


Ten*_*r04 6

我认为这可以归结为他们的后端如何启动 VM 并测量时间。因为这也需要大约 200 毫秒,这太荒谬了:

class Solution {
    fun numDistinct(s: String, t: String): Int {
        return 3
    }
}
Run Code Online (Sandbox Code Playgroud)

我怀疑无论代码多么简单,您都可以指望大约 200 毫秒的预热时间。尽管奇怪的是,我尝试编辑这两个函数以在返回之前重复该算法一百万次,并且 Kotlin 代码(在调整如下所述的等效性之后)始终显示较低的运行时间。

不过,您的代码并不完全等同于 Java。另一个答案已经提到了您的内部数组类型。

与性能无关,但您的第一个循环在 Java 中比在 Kotlin 中多填充了一个空间。