The Gradle Daemon

什么是 Gradle 的守护进程

维基百科中守护进程的解释

守护进程是一个运行后台进程, 非交互式用户直接控制的在计算机程序

Gradle 守护进程是一个后台进程, 它运行着繁重的构建, 然后在构建等待下一次构建的之间保持自身存在. 这使得数据和代码在下一次构建前已经准备好,并存入内存中. 这显著的提高了后续构建的性能. 启用Gradle守护进程是一种节约构建时间的廉价方式.

强烈建议在所有开发机器上启用Gradle的守护进程.但是不推荐在持续集成和构建服务器环境下启用守护进程(参见 Section 18.3, “When should I not use the Gradle Daemon?”).

Gradle自动管理守护进程.如果构建环境配置为利用后台程序,如果在没有可用守护进程,就会自动启动一个守护进程,或者使用现有的空闲的兼容守护进程.如果一个守护进程在3个小时内没有使用,它将会自我终结.一旦配置开发环境为使用的守护进程,守护进程通常是隐形的,容易被遗忘的.

管理和配置

如何启动Gradle的守护进程

在使用Gradle命令行接口时,--daemon--no-daemon命令行选项调用在单个构建时选择启用或禁用后台守护进程.通常,允许后台守护进程在一个环境中(例如一个用户账户)更为方便,可以使所有构建使用守护进程,而不需要记住--daemon开关.

有两种推荐的方式使守护进程持续与环境:

  1. 通过环境变量 - 给GRADLE_OPTS环境变量添加-Dorg.gradle.daemon=true标识
  2. 通过属性文件 - 给<<GRADLE_USER_HOME>>/gradle.properties文件添加org.gradle.daemon=true

注意:<<GRADLE_USER_HOME>>默认为<<USER_HOME>>/.gradle,<<USER_HOME>>为当前用户home目录,这个位置可以通过-g-gradle-user-home命令行选项,以及由GRADLE_USER_HOME环境变量org.gradle.user.home JVM系统属性配置。

这两种方法有同样的效果,使用哪一个是由个人喜好.大多数Gradle用户选择第二个方式,给gradle.properties并添加条目.

在Windows中,该命令将使当前用户启用守护:

(if not exist "%HOMEPATH%/.gradle" mkdir "%HOMEPATH%/.gradle") && (echo foo >> "%HOMEPATH%/.gradle/gradle.properties")

在类Unix操作系统,以下的Bash shell命令将使当前用户启用守护进程:

touch ~/.gradle/gradle.properties && echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties

一旦以这种方式在构建环境中启用了守护进程,所有的构建将隐含一个守护进程.

如何禁用Gradle的守护进程

一般Gradle守护进程默认不启用.然而,一旦它被启用,有事希望对某些项目或某些构建禁用守护进程.

--no-daemon命令行选项可用于强制守护进程不能用于该构建.这很少使用,但是在调试具有一定的构建或Gradle插件问题时,有时会很有用.在构建环境中,此命令行选项具有最高优先级.

怎样抑制“please consider using the Gradle Daemon”消息

Gradle可能会在构建结束时发出建议您使用Gradle守护进程的末尾警告.为了避免这个警告,您可以通过上述的这些方法使用守护进程,或者明确禁用守护进程.您可以通过上述的--no daemon的命令行选项明确禁用守护进程,或使用上述的org.gradle.deamon的值设置为false代替trie.

因为不建议在持续集成构建中使用守护进程,如果CI环境变量已存在,Gradle不会发出此消息.

为什么会在机器上出现不只一个守护进程

有几个原因Gradle会创建一个新的守护进程代替使用一个已存在的守护进程.如果守护进程没有闲置,兼容,则会启动一个新的守护进程.

空闲的守护进程是当前未执行构建或做其他有用的工作.

兼容的守护进程是一个可以(或者可以达到)满足要求的编译环境的要求。Java安装程序运行的构建是构建环境方面的一个例子。构建运行时所需的JVM系统属性是另一个例子。

一个已经运行的Java进程可能不能满足所需的构建环境的某些方面。如果守护进程由Java7启动,但要求的环境要求为Java8,则守护进程是不兼容的,必须另外启动。再者,在运行的JVM不能改变一个运行时的某些性能。如内存分配(如-Xmx1024m),默认文本编码运行的JVM中,默认的语言环境,等等一个JVM不能改变的运行环境。

"Required build environment"通常在构建客户端(如Gradle命令行,IDE等)方面隐含构建环境,并明确通过命令行选项设置.参见Chapter 20,The Build Environment有关如何指定和控制构建环境的详细信息.

一下JVM系统属性是有效不变的.如果需求编译环境需要这些属性,不同的守护进程JVM在下列属性中有不同的值时,守护进程不兼容.

  • file.encoding
  • user.language
  • user.country
  • user.variant
  • com.sun.management.jmxremote

下列JVM属性,通过启动参数控制,也是有效不变的.在需求构建环境和守护进程环境的对应属性必须按顺序完全匹配,才可兼容.

  • 最大堆大小(即 -Xmx JVM参数)
  • 最小堆大小(即 -Xms JVM参数)
  • 引导类路径(即 -Xbootclasspath JVM参数)
  • "assertion"状态(即 -ea 参数)

所需的Gradle版本是需求构建环境的另一个方面.守护进程被耦合到特定Gradle运行时,多个正在运行的守护进程产生的原因是使用使用不同版本的Gradle会在会话过程中处理多个项目.

守护进程占用多大内存并且能不能给它更大的内存?

如果需求构建环境没有指定最大堆内存,守护进程会使用多达1G的堆内存.它将会使用默认的JVM的最小堆内存.1G内存足够应付大多数构建.有数百个子项的构建,大量配置或者源码需求,或者要求有更好的表现,则需要更多地内存

为了提高守护进程可以使用的内存,指定相应的标志作为需求构建环境的一部分,请参见Chapter 20. The Build Environment的详细信息.

如何停止守护进程

守护进程会在闲置3小时后自动终止.如果想在这之前停止守护进程,也可以通过操作系统运行gradle --stop命令终止后台进程.--stop选项会要求所有运行相同版本的守护进程终止.

守护进程何时会出错

许多工程设计已经加入守护进程使得守护进程在日常的开发中变得更加健壮,透明和不起眼.无论如何,守护进程偶尔也会损坏或者枯竭.一个Gradle构建执行源自多个来源的任意代码.即使Gradle本身与守护进程的设计是经过严格的测试的,但是用户的构建脚本,或第三方插件可以通过诸如内存泄露,或腐化全局声明等缺陷来动摇守护进程.

另外,也可以通过构建时进行不正确的资源释放,也可能会动摇守护进程(构建环境正常).在在Microsoft Windows下是一个特别尖锐的问题,在程序读写文件后关闭失败的处理是非常随意的.

如果出现守护进程不稳定情况,可以简单的终止.回顾一下--no-daemon的选项可以用于构建阻止使用守护进程,这对于检验一个问题的罪魁祸首是不是守护进程很有帮助.

什么时候不使用Gradle守护进程

建议在开发环境中使用Gradle的守护进程,不建议在持续集成环境和构建服务器环境中使用守护进程.

守护进程可以更快的构建,这对于一个正坐在椅子前构建项目的人来说非常重要.对于CI构建来说,稳定性和可预见性是最重要的.为每个构建运行时用一个新的,完全孤立于以前的版本的程序,更加可靠。

工具和集成开发环境

Gradle工具API(参见Chapter.65.Embedding Gradle),用于IDEs和其他工具整合Gradle,是使用Gradle守护进程执行构建.如果你是从IDE内部执行构建,那么你是在使用守护进程,而且不需要在你的环境中允许Gradle守护进程.

但是,除非您已明确启用的Gradle守护进程在你的环境的,你在命令行中的构建不会使用摇篮守护进程。

摇篮守护进程如何使构建速度更快

Gradle守护进程是一个常驻构建进程.在两个构建之间的空闲期间会等待着下次构建.与每个构建加载Gradle到内存相比,对于多个构建只需要加载一次Gradle到内存具有明显的好处.这本身就是对性能的显著优化,但是不止这些.

现代JVM的显著优化是运行时代码优化.例如,热点(HotSpot)(由Oracle提供并作为OpenJDK的基础的JVM实现)适用于优化运行时代码.优化是渐进的,而不是瞬间的。也就是说,代码在运行期间逐步优化,这意味着后续版本纯粹是基于这个优化过程变得更快.HotSpot实验表明,它需要5至10某处构建以优化至稳定.在一个守护进程的第一个构建和第十之间感知的编译时间的差异可以说是相当巨大的.

守护程序还允许更有效地在内存中缓存整个构建。例如,需要构建(如插件,构建脚本)的类可以在内存中举行的构建。同样,摇篮可保持在内存中缓存的构建数据的诸如的任务输入和输出的哈希值,用于增量构建。

未来可能的改进

目前,守护使构建速度更快有效地支持在内存中缓存和由JVM优化使代码更快。在未来的Gradle版本中,守护进程将变得更加聪明,预先完成工作。它可能,例如,在编辑完构建脚本后就开始下载依赖生成是将要运行的假设下后立即和新改变或添加的依赖性是必需的。

有许多方式使得在未来的版本的gradle的gradle守护进程。