【问题标题】:Clojure application startup performanceClojure 应用程序启动性能
【发布时间】:2011-05-26 13:16:43
【问题描述】:

我在 Clojure 中编写了一些小型实用程序应用程序,我使用 Maven 和 maven-shade-plugin 将它们编译成独立的可执行 JAR 文件(“uberjars”)。这些 uberjars 包含 clojure.jar 的解压版本和应用程序依赖的其他库(即:commons-cli)。它们很方便,因为我可以将它们发送给客户,而无需客户安装 Clojure(所有客户都已经安装了 JRE)。

我发现 Clojure 应用程序需要几秒钟才能启动,而用 Java 编写的类似应用程序在同一台机器上启动只需亚秒级(例如,显示使用消息的时间)。

我怀疑这是因为 Clojure 正在即时编译 clojure.core 库中的一些代码,因为 clojure.jar 文件中有源代码(.clj 文件)。

有没有办法预编译这个源代码?可以做些什么来加快启动性能吗?我听到客户抱怨启动需要多长时间(他们不知道也不关心应用程序是用 Clojure 或 Java 或 Foobar 编写的)。

【问题讨论】:

标签: performance clojure startup


【解决方案1】:

JVM(至少是 Oracle 的 HotSpot)在减少启动时间方面非常棘手。它不会将所有程序的类和方法加载到内存中,它会仅加载它现在需要的资源。不需要太多代码来显示使用消息或类似的东西,因此实际上只加载了几个函数,Java 程序就可以快速启动。此外,HotSpot 甚至不编译这几个函数 - 它使用 JIT 编译(和其他优化)来重复执行代码。没有理由花时间编译只执行一次的函数,例如几乎所有的启动方式,而HotSpot没有。

那么,Clojure 呢?我认为您不想重写 Clojure 的核心来添加类似的功能。不过,您可以在 Clojure 代码中使用相同的方法。您说您的实用程序使用了几个库,这可能会减慢启动速度。因此,尽可能延迟加载库。例如,您可以从命名空间定义中排除:use 选项,并在您的主体函数中调用显式use。这不会减少总时间,但会将时间转移到不那么明显的时刻。您甚至可以用 Java 编写程序的一小部分,并仅在实际需要时调用 Clojure 代码。

【讨论】:

  • 您好,上述解决方案肯定会带来性能提升,但代价​​是什么? !好消息是,在 Clojure 1.3 中,有一个实验性功能(唉,“暂时禁用”,正如最近在 github 上的提交中所写的那样),其目的是启用已编译 fns 的“延迟加载”。
【解决方案2】:

在 Clojure 网站上有一个很好的描述 AOT compilation。这已经节省了一些启动时间。

编辑:已经尝试在持久的 JVM 上运行 Clojure 程序,从而减少启动时间。查找 jark + jvm。但是该网站似乎已经消失了:(

【讨论】:

  • 我已经用我自己的代码进行了 AOT,并且只在 JAR 中包含了 .class 文件,但似乎 clojure.core 必须包含一些在应用程序启动时得到编译的源代码,除非我离基地很远,起步缓慢是由于其他原因。您是否建议使用 AOT 重建 clojure.jar?
  • 别担心,虽然clojure.jar有一些.clj文件,但它也有对应的.class文件。启动缓慢主要是由于每次执行 Clojure 实用程序时 JVM 启动时间。
  • "每次执行 Clojure 实用程序时,启动缓慢主要是由于 JVM 启动时间。" -- 如果这是真的,为什么 Java 应用程序会在一秒钟内启动(Macbook Pro 2.66 GHz Core i7、9GB RAM、OsX 10.6.7)?
【解决方案3】:

当然,还有用于提高 JVM 启动性能的 java -client JVM 参数。这个SO question 详细介绍了这个主题。

【讨论】:

    猜你喜欢
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    相关资源
    最近更新 更多