【问题标题】:How do I speed up the gwt compiler?如何加快 gwt 编译器的速度?
【发布时间】:2010-11-03 22:55:09
【问题描述】:

我们开始在我们的项目中更多地使用 GWT,而 GWT 编译器的性能变得越来越烦人。

我们将开始改变我们的工作实践以缓解该问题,包括更加强调托管模式浏览器,它将运行 GWT 编译器的需要推迟到以后,但这也带来了风险,特别是直到比我们想要的晚得多时才发现真正的浏览器的问题。

理想情况下,我们希望 GWT 编译器本身更快 - 编译一个相当小的应用程序需要一分钟时间。但是,我们使用 compile 是一种相当幼稚的方式,所以我希望我们可以快速轻松地获得一些收益。

我们目前正在调用 com.google.gwt.dev.Compiler 作为来自 ant Ant 目标的 java 应用程序,具有 256m 的最大堆和大量堆栈空间。编译器由 Ant 使用 fork=true 和最新的 Java 6 JRE 启动,以尝试利用 Java6 改进的性能。我们将主控制器类与应用程序类路径一起传递给编译器,然后就可以了。

我们还能做些什么来获得额外的速度?我们能不能给它更多的信息,让它花更少的时间去发现要做什么?

我知道我们可以告诉它只编译一个浏览器,但我们需要做多浏览器测试,所以这不太实用。

此时欢迎所有建议。

【问题讨论】:

    标签: java performance gwt


    【解决方案1】:

    让我们从令人不安的事实开始:GWT 编译器的性能真的很糟糕。您可以到处使用一些技巧,但不会获得明显更好的性能。

    你可以做的一个很好的性能破解是只为特定的浏览器编译,通过在你的gwt.xml中插入以下行:

    <define-property name="user.agent" values="ie6,gecko,gecko1_8"></define-property>
    

    或使用 gwt 2.x 语法,并且仅适用于一个浏览器:

    <set-property name="user.agent" value="gecko1_8"/>
    

    例如,这将只为 IE 和 FF 编译您的应用程序。如果您知道您只使用特定的浏览器进行测试,您可以使用这个小技巧。

    另一种选择:如果您使用多个语言环境,并且再次只使用一个进行测试,您可以将它们全部注释掉,以便 GWT 将使用默认语言环境,这会减少编译时的一些额外开销。

    底线:您不会在编译器性能上获得数量级的提升,但是通过几次放松,您可以在这里和那里节省几分钟。

    【讨论】:

    • 它出现在 GWT 2.0 中,你实际上希望这个语法来指定一个用户代理:
    • 在 gwt 2.2 中没有壁虎。编译器指出“先前未定义值 gecko。处理元素 'set-property' 时出现意外异常”
    • 将值设置为“gecko1_8”仅适用于 Firefox 1.5 及更高版本的 gwt 2.2
    • 这个答案已经快两年了。随意编辑它以澄清这一点。
    • 2013,GWT 编译时间仍然很糟糕,任何人都可以改进这个答案,GWT 2.5
    【解决方案2】:

    如果您使用 -localWorkers 标志运行 GWT 编译器,编译器将并行编译多个排列。这使您可以使用多核机器的所有内核,例如 -localWorkers 2 将告诉编译器并行编译两个排列。 您不会得到数量级的差异(并非编译器中的所有内容都是可并行化的),但如果您正在编译多个排列,它仍然是一个显着的加速。

    如果您愿意使用 GWT 的中继版本,您将能够对任何浏览器 (out of process hosted mode) 使用托管模式,这可以缓解当前托管模式的大部分问题。这似乎是 GWT 的发展方向 - 始终使用托管模式进行开发,因为编译不太可能更快地获得数量级。

    【讨论】:

    • 啊,localWorkers 选项是个好东西,值得了解。可悲的是,我们的大多数开发盒都是单核至强。 OOPHM 看起来也很有希望。总是在下一个版本中,它是......
    • 在多核机器上虚拟化编译环境;远程进入这个虚拟机;使用 -localWorkers 执行命令行 GWT 编译,使用最少的 locals 和 user.agents;确保托管 vm 的框是您要部署到的网络对等体。结合使用,在 tomcat 中部署时,您的编译时间缩短到大约 30 秒。此外,所有这些都可以写在脚本中。您还可以在本地机器上开发,创建一个 svn 补丁,并让您的脚本使用某种类型的 NFS 或 samba 共享来应用补丁,从而无需仅复制 src 差异。耶!
    • NX 客户端也是一个巨大的 +++ 用于在有限的 ADSL、电缆或 WiFi 连接上进行远程开发。此外,无论您在任何带互联网的位置使用什么组合,您都始终保持同步
    • 默认为 maven 构建中的平台可用 CPU 数量。所以我这里没有加速。
    【解决方案3】:

    虽然这个条目已经很老了,而且你们中的大多数人可能已经知道了,但我认为值得一提的是,GWT 2.x 包含一个新的编译标志,它通过跳过优化来加速编译。您绝对不应该部署以这种方式编译的 JavaScript,但在非生产连续构建期间它可以节省时间。

    只需在您的 GWT 编译器行中包含标志:-draftCompile。

    【讨论】:

    • 我使用了该选项,但在我们的项目中,有时它会因奇怪的错误而失败。所以请注意,有时编译可能会因此而无法正常工作。
    【解决方案4】:

    Here is a list of user.agent values你可以设置成。

    (在此处添加此内容是因为当我搜索应设置的内容以使其仅产生 chrome 的排列时,我一直在此处结束。答案是:&lt;set-property name="user.agent" value="safari"/&gt;

    【讨论】:

    • 我应该在哪里添加这个 set-property 元素?我尝试在 app.gwt.xml 文件的 元素内部和外部添加它,但它不起作用。
    • 它在您的模块 ABC.gwt.xml 文件中,其中 ABC 是您的模块名称。
    【解决方案5】:

    在 GWT 的较新版本中(我相信从 2.3 或 2.4 开始),您还可以添加

    <collapse-all-properties />
    

    到您的 gwt.xml 用于开发目的。 这将告诉 GWT 编译器创建一个涵盖所有语言环境和浏览器的单一排列。因此,您仍然可以在所有浏览器和语言中进行测试,但仍然只编译一个排列

    【讨论】:

    • 有趣...有什么缺点?
    • 编译处理所有浏览器和语言的单一排列仍然比只处理一种浏览器和语言的单一排列要多一点时间,但根据我的经验,差异并不显着。 (我所看到的大约多出 25%,但这仍然是编译多个排列的巨大改进)
    • 我找不到这个的文档链接...你能链接到什么吗?
    • 虽然这个标签加快了编译速度,但它也破坏了超级开发模式下的调试(至少对于 2.6)。 chrome 调试器中显示的源代码与编译后的 js 代码不同。因此,当我在某个 java 方法中设置断点时,调试器会在另一个方法中停止。
    【解决方案6】:

    您可以在构建中添加一个选项以用于生产:

    -localWorkers 8—— 其中 8 是计算排列的并发线程数。您所要做的就是将此数字调整为对您更方便的数字。请参阅GWT compilation performance(感谢 Dennis Ich 的评论)。

    如果是编译到测试环境,也可以使用:

    -draftCompile 可以实现更快但优化程度较低的编译

    -optimize 0 不会优化您的代码(9 是最大优化值)

    另一个使构建和托管模式性能提高一倍以上的事情是使用 SSD 磁盘(现在托管模式就像一个魅力)。这不是一个便宜的解决方案,但取决于您使用 GWT 的程度和您的时间成本,这可能是值得的!

    希望对您有所帮助!

    【讨论】:

    • 将本地工作人员设置为核心数量可能会非常低效。请参阅此内容以供参考:josephmarques.wordpress.com/2010/07/30/…
    • 感谢您评论丹尼斯。实际上,我有一个SSD并提供2G内存。当然,localWorker 的数量必须针对每种情况进行调整,具体取决于排列、内核、机器等的数量......在我的情况下,当我在笔记本电脑上编译并想在网络上导航时,如果留出 2 个内核。这只是一个例子。但是,将编辑我的帖子以包含您的想法。谢谢。
    【解决方案7】:

    GWT 编译器正在执行大量代码分析,因此很难加快速度。 This session from Google IO 2008 会让您很好地了解 GWT 正在做什么以及为什么需要这么长时间。

    我的建议是开发尽可能使用托管模式,然后仅在您想要进行测试时进行编译。这听起来确实像您已经找到的解决方案,但基本上这就是托管模式存在的原因(嗯,那个和调试)。

    你可以加快 GWT 的编译速度,但只针对某些浏览器编译,而不是 GWT 默认编译的 5 种。如果您想使用托管模式,请确保您为至少两个浏览器进行编译;如果您针对单个浏览器进行编译,则浏览器检测代码会被优化掉,然后托管模式将不再起作用。

    为更少的浏览器配置编译的一种简单方法是创建第二个从主模块继承的模块:

    <module rename-to="myproject">
      <inherits name="com.mycompany.MyProject"/>
      <!-- Compile for IE and Chrome -->
      <!-- If you compile for only one browser, the browser detection javascript
           is optimised away and then Hosted Mode doesn't work -->
      <set-property name="user.agent" value="ie6,safari"/>
    </module>
    

    如果rename-to 属性设置相同,则输出文件将与您进行完整编译时相同

    【讨论】:

      【解决方案8】:
      • 将您的应用程序拆分为多个模块或入口点,然后仅在需要时重新编译。
      • 使用提供Story of your compile 的主干版本分析您的应用程序。这可能与 1.6 编译器相关,也可能不相关,但它可以指示正在发生的事情。

      【讨论】:

      • 多个入口点应该可以工作,但模块不能工作,因为 GWT 总是检查与您的代码相关的所有内容并编译一个整体的最终结果。 GWT 框架是一团糟,是模块化原则的耻辱。没有找到一个可以重用 GWT 框架的好项目。
      【解决方案9】:

      对于 GWT 2.x,我刚刚发现如果你使用

      <set-property name="user.agent" value="ie6"/>
      <extend-property values="ie8,gecko1_8" name="user.agent"/>
      

      您甚至可以指定多个排列。

      【讨论】:

        【解决方案10】:

        你可以编译gwt的特定模块 只需在项目的 build.xml 中提及要编译的模块即可。

        借助下面的命令

        ant -Dap.build.javadoc gwt
        

        【讨论】:

          猜你喜欢
          • 2014-07-24
          • 1970-01-01
          • 2011-04-03
          • 1970-01-01
          • 2014-06-10
          • 1970-01-01
          • 2017-06-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多