在Clojure中运行Java代码的速度与Java中的Java相同

时间:2012-03-31 14:25:20

标签: clojure

我有以下代码:

(let [obs ^java.util.Observer (proxy [java.util.Observer] []
              (update [^Object o ^String arg]
                (println arg)))
        network ^StockPriceNeuralNetwork (NeuralNetworkFactory/createStockMarketNeuralNetwork ^java.util.List [^java.util.Observer obs])]
    (.trainForTime ^StockPriceNeuralNetwork network))

问题来自Java,这段代码运行的速度比编译代码时从Clojure调用代码快大约100倍。有没有什么方法可以从Clojure中获取相同的Java性能,或者它总是会变慢?

1 个答案:

答案 0 :(得分:8)

这里有更多的类型提示,而你所拥有的那些类型提示使得我不能完全确定它们有什么好处 - 你真的应该在let中暗示这个名字,不是价值。也就是说,(let [^Observer obs (...)] ...),而不是(let [obs ^Observer (...)] ...)。在许多情况下,这两种方法都有效,但前者更“安全”。同样,你应该强烈要求reify超过proxy这里的性能,因为当你可以避免使用proxy时,我们不鼓励这样做。

我不知道你正在使用什么神经网络库,所以你可能需要一个关于createStockMarketNeuralNetwork的参数的单一类型提示,但其余的没有任何意义,除了混淆任何读取代码的人 - 如果选择不准确的提示,那么过多的类型提示甚至可能会使编译器混淆写入较慢的代码。因此,不要在整个代码中随意放置它们,而是切换到reify方法sw1nn建议,然后将*warn-on-reflection*设置为true,并查看反射是什么(如果有的话)。以下是此代码的reify版本,在删除了我知道的所有类型提示后没有区别:

(let [obs (reify java.util.Observer
            (update [this o arg]
              (println arg)))
      ^StockPriceNeuralNetwork network (NeuralNetworkFactory/createStockMarketNeuralNetwork ^java.util.List [obs])]
  (.trainForTime network))