我在clojure和scala中编写了一个编辑距离算法。使用java原始数组的clojure代码比scala版本慢70倍
scala版本比clojure版本运行速度快70倍。
的Clojure:
(defn edit-distance
"['seq of char' 'seq of char']"
[s0 s1]
(let [n0 (count s0)
n1 (count s1)
distances (make-array Long/TYPE (inc n0) (inc n1))]
;;initialize distances
(doseq [i (range 1 (inc n0))] (aset-long distances i 0 i))
(doseq [j (range 1 (inc n1))] (aset-long distances 0 j j))
(doseq [i (range 1 (inc n0)), j (range 1 (inc n1))]
(let [ins (aget distances i (dec j))
del (aget distances (dec i) j)
match (aget distances (dec i) (dec j))
min-dist (min ins del match)]
(cond
(not= match min-dist) (aset-long distances i j (inc min-dist))
(not= (nth s0 (dec i)) (nth s1 (dec j))) (aset-long distances i j (inc min-dist))
:else (aset-long distances i j min-dist))))
(aget distances n0 n1)))
阶:
def editDistance(s0: Array[Char], s1: Array[Char]):Int = {
val n0 = s0.length
val n1 = s1.length
val distances = Array.fill(n0+1)(ArrayBuffer.fill(n1+1)(0))
for(j <- 0 to n1){distances(0)(j) = j}
for(i <- 0 to n0){distances(i)(0) = i}
for(i <- 1 to n0; j <- 1 to n1){
val ins = distances(i)(j-1)
val del = distances(i-1)(j)
val matches = distances(i-1)(j-1)
val minDist = (ins::del::matches::Nil).reduceLeft(_ min _)
if (matches != minDist)
distances(i)(j) = minDist + 1
else if (s0(i-1) == s1(j-1))
distances(i)(j) = minDist
else
distances(i)(j) = minDist + 1
}
distances(n0)(n1)
}
我使用Clojure中的Java的阵列,以获得最佳的性能。我已经考虑暗示每当调用aget
,但我的代码执行更糟糕(这可能是因为make-array
已经定义了一个类型数组)。我也在projects.clj中覆盖clojure :jvm-opts
。然而,我得到的性能差距是70倍。
我在clojure中使用java数组有什么问题?
感谢您的洞察力。
你有没有通过运行这个**探查**?尤其要注意内存消耗。 –
@ Anony-Mousse确实通过_java.lang.reflect.method_消耗> 90%的内存做了反思。考虑到2d数组输入的距离,怎么会发生这种情况? – user3639782
也许一些lambda表达式。 clojure是否使用方法引用生成Java 8字节码? –