Spec-Zone.ru › Kotlin 1.8

Компиляция и кэши в плагине Kotlin Gradle

На этой странице вы можете узнать о следующих темах:

  • Инкрементальная компиляция

  • Поддержка кэша сборки Gradle

  • Поддержка кэша конфигурации Gradle

  • Демон Kotlin и как использовать его с Gradle

  • Определение стратегии выполнения компилятора Kotlin

  • Стратегия обратного вызова компилятора Kotlin

  • Отчеты о сборке

Инкрементальная компиляция

Плагин Kotlin Gradle поддерживает инкрементальную компиляцию. Инкрементальная компиляция отслеживает изменения в исходных файлах между сборками, чтобы компилировались только файлы, затронутые этими изменениями.

Инкрементальная компиляция поддерживается для проектов Kotlin/JVM и Kotlin/JS и включена по умолчанию.

Существует несколько способов отключить инкрементальную компиляцию:

  • Установите kotlin.incremental=false для Kotlin/JVM.

  • Установите kotlin.incremental.js=false для проектов Kotlin/JS.

  • Используйте -Pkotlin.incremental=false или -Pkotlin.incremental.js=false в качестве параметра командной строки.

    Параметр необходимо добавить в каждую последующую сборку.

Примечание: любая сборка с отключенной инкрементальной компиляцией делает кэши инкрементальной компиляции недействительными. Первая сборка никогда не является инкрементальной.

Иногда проблемы с инкрементальной компиляцией становятся видны через несколько циклов после возникновения ошибки. Используйте отчеты о сборке, чтобы отслеживать историю изменений и компиляций. Это может помочь в предоставлении воспроизводимых отчетов об ошибках.

Новый подход к инкрементальной компиляции

Новый подход к инкрементальной компиляции экспериментальный. Он может быть удален или изменён в любое время. Необходима подписка (см. подробности ниже). Мы рекомендуем использовать его только для оценки и будем признательны за обратную связь в YouTrack.

Новый подход к инкрементальной компиляции доступен начиная с Kotlin 1.7.0 для JVM-бекенда в системе сборки Gradle. Этот подход поддерживает изменения, внесённые в зависимые модули, не написанные на Kotlin, включает улучшенную возможность избежания компиляции и совместим с кэшем сборки Gradle.

Все эти улучшения уменьшают количество неинкрементальных сборок, что ускоряет общую время компиляции. Вы получите наибольшую выгоду, если используете кэш сборки или часто вносите изменения в не-Kotlin модули Gradle.

Чтобы включить этот новый подход, установите соответствующий параметр в вашем gradle.properties.

kotlin.incremental.useClasspathSnapshot=true

Узнайте, как реализован новый подход к инкрементальной компиляции в этой статье блога.

Поддержка кэша сборки Gradle

Плагин Kotlin использует кэш сборки Gradle, который хранит выходные данные сборки для повторного использования в будущих сборках.

Чтобы отключить кэширование для всех задач Kotlin, установите системную переменную kotlin.caching.enabled в false (запустите сборку с аргументом -Dkotlin.caching.enabled=false).

Если вы используете kapt, обратите внимание, что задачи аннотационной обработки kapt по умолчанию не кэшируются. Однако, вы можете включить кэширование для них вручную.

Поддержка кэша конфигурации Gradle

Поддержка кэша конфигурации Gradle имеет некоторые ограничения:

  • Кэш конфигурации доступен в Gradle 6.5 и более поздних версиях в качестве экспериментальной функции.
    > Вы можете проверить страницу релизов Gradle, чтобы узнать, стала ли она стабильной.

  • Функция поддерживается только следующими плагинами Gradle: > * org.jetbrains.kotlin.jvm

    • org.jetbrains.kotlin.js

    • org.jetbrains.kotlin.android

Плагин Kotlin использует кэш конфигурации Gradle, который ускоряет процесс сборки, повторно используя результаты фазы конфигурации.

См. документацию Gradle, чтобы узнать, как включить кэш конфигурации. После включения этой функции, плагин Kotlin Gradle автоматически начнёт его использовать.

Демон Kotlin и его использование с Gradle

Демон Kotlin:

  • Запускается вместе с демоном Gradle для компиляции проекта.

  • Запускается отдельно от демона Gradle, когда вы компилируете проект с помощью встроенной системы сборки IntelliJ IDEA.

Демон Kotlin запускается на стадии выполнения Gradle исполнения, когда одна из задач компиляции Kotlin начинает компилировать исходные файлы. Демон Kotlin останавливается вместе с демоном Gradle или через два часа бездействия без компиляции Kotlin.

Демон Kotlin использует ту же JDK, что и демон Gradle.

Установка аргументов JVM для демона Kotlin

Каждый из следующих способов установки аргументов переопределяет предыдущие:

  • Наследование аргументов демона Gradle

  • kotlin.daemon.jvm.options системная переменная

  • kotlin.daemon.jvmargs свойство

  • kotlin расширение

  • Определение конкретной задачи

Наследование аргументов демона Gradle

Если ничего не указано, демон Kotlin наследует аргументы от демона Gradle. Например, в файле gradle.properties:

org.gradle.jvmargs=-Xmx1500m -Xms=500m

Системная переменная kotlin.daemon.jvm.options

Если у аргументов JVM демона Gradle есть системная переменная kotlin.daemon.jvm.options – используйте её в файле gradle.properties:

org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,Xms=500m

При передаче аргументов следуйте этим правилам:

  • Используйте знак минус - только перед аргументами Xmx, XX:MaxMetaspaceSize, и XX:ReservedCodeCacheSize.

  • Разделяйте аргументы запятыми (, ) без пробелов. Аргументы, следующие за пробелом, будут использованы для демона Gradle, а не для демона Kotlin.

Gradle игнорирует эти свойства, если выполняются все следующие условия:

  • Gradle использует JDK 1.9 или выше.

  • Версия Gradle находится в диапазоне от 7.0 до 7.1.1 включительно.

  • Gradle компилирует скрипты Kotlin DSL.

  • Демон Kotlin не запущен.

Для решения этой проблемы, обновите Gradle до версии 7.2 (или выше) или используйте свойство kotlin.daemon.jvmargs – см. следующий раздел.

Свойство kotlin.daemon.jvmargs

Вы можете добавить свойство kotlin.daemon.jvmargs в файле gradle.properties:

kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m

Расширение kotlin

Вы можете указать аргументы в расширении kotlin:

kotlin {
    kotlinDaemonJvmArgs = listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC")
}
kotlin {
    kotlinDaemonJvmArgs = ["-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"]
}

Определение конкретной задачи

Вы можете указать аргументы для конкретной задачи:

tasks.withType<CompileUsingKotlinDaemon>().configureEach {
    kotlinDaemonJvmArguments.set(listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"))
}
tasks.withType(CompileUsingKotlinDaemon::class).configureEach { task ->
    task.kotlinDaemonJvmArguments.set(["-Xmx1g", "-Xms512m"])
}

В этом случае новый экземпляр демона Kotlin может запуститься при выполнении задачи. Узнайте больше о поведении демона Kotlin с аргументами JVM.

Поведение демона Kotlin с аргументами JVM

При настройке аргументов JVM для демона Kotlin обратите внимание на следующее:

  • Ожидается, что несколько экземпляров демона Kotlin будут работать одновременно, когда разные подпроекты или задачи имеют различные наборы аргументов JVM.

  • Новый экземпляр демона Kotlin запускается только при выполнении Gradle связанной задачи компиляции, и существующие демоны Kotlin не имеют одинакового набора аргументов JVM. Представьте, что ваш проект содержит множество подпроектов. Большинство из них требуют некоторого объема памяти для демона Kotlin, но один модуль требует значительного объема (хотя и компилируется редко). В этом случае вы должны предоставить другой набор аргументов JVM для такого модуля, чтобы демон Kotlin с большим объемом памяти запускался только для разработчиков, работающих с этим конкретным модулем.

    Если вы уже запускаете демон Kotlin, у которого достаточно памяти для обработки запроса компиляции, даже если другие запрошенные аргументы JVM отличаются, этот демон будет повторно использован вместо запуска нового.

  • Если аргумент Xmx не указан, демон Kotlin унаследует его от демона Gradle.

Определение стратегии выполнения компилятора Kotlin

Стратегия выполнения компилятора Kotlin определяет место выполнения компилятора Kotlin и поддерживается ли инкрементная компиляция в каждом случае.

Существует три стратегии выполнения компилятора:

Стратегия

Место выполнения компилятора Kotlin

Инкрементная компиляция

Другие характеристики и замечания

Демон

Внутри собственного демона процесса

Да

По умолчанию и самая быстрая стратегия. Может быть совмещена между различными демонами Gradle и несколькими параллельными компиляциями.

В процессе

Внутри процесса демона Gradle

Нет

Может совместно использовать кучу с демоном Gradle. Стратегия выполнения "В процессе" медленнее, чем стратегия "Демон". Каждый воркер создаёт отдельный класслоадер компилятора Kotlin для каждой компиляции.

Вне процесса

В отдельном процессе для каждой компиляции

Нет

Самая медленная стратегия выполнения. Похожа на стратегию "В процессе", но дополнительно создаёт отдельный процесс Java внутри воркера Gradle для каждой компиляции.

Для определения стратегии выполнения компилятора Kotlin можно использовать одно из следующих свойств:

  • kotlin.compiler.execution.strategy свойство Gradle.

  • compilerExecutionStrategy свойство задачи компиляции.

Свойство задачи compilerExecutionStrategy имеет приоритет над свойством Gradle kotlin.compiler.execution.strategy.

Доступные значения для свойства kotlin.compiler.execution.strategy:

  1. daemon (по умолчанию)

  2. in-process

  3. out-of-process

Используйте свойство Gradle kotlin.compiler.execution.strategy в файле gradle.properties:

kotlin.compiler.execution.strategy=out-of-process

Доступные значения для свойства задачи compilerExecutionStrategy:

  1. org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.DAEMON (по умолчанию)

  2. org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.IN_PROCESS

  3. org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.OUT_OF_PROCESS

Используйте свойство задачи compilerExecutionStrategy в ваших скриптах сборки:

import org.jetbrains.kotlin.gradle.tasks.CompileUsingKotlinDaemon
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy

// ...

tasks.withType<CompileUsingKotlinDaemon>().configureEach {
    compilerExecutionStrategy.set(KotlinCompilerExecutionStrategy.IN_PROCESS)
} 
import org.jetbrains.kotlin.gradle.tasks.CompileUsingKotlinDaemon
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy

// ...

tasks.withType(CompileUsingKotlinDaemon)
    .configureEach {
        compilerExecutionStrategy.set(KotlinCompilerExecutionStrategy.IN_PROCESS)
    }

Стратегия резервного копирования компилятора Kotlin

Стратегия резервного копирования компилятора Kotlin заключается в запуске компиляции вне демона Kotlin, если демон по какой-то причине терпит неудачу. Если демон Gradle активен, компилятор использует стратегию "В процессе". Если демон Gradle выключен, компилятор использует стратегию "Вне процесса".

Когда происходит эта резервная стратегия, в выходных данных сборки Gradle отображаются следующие предупреждающие строки:

Failed to compile with Kotlin daemon: java.lang.RuntimeException: Could not connect to Kotlin compile daemon
[exception stacktrace]
Using fallback strategy: Compile without Kotlin daemon
Try ./gradlew --stop if this issue persists.

Однако, пассивное переключение на другую стратегию может потреблять много системных ресурсов или приводить к непредсказуемым сборкам. Подробнее об этом можно прочитать в этом вопросе на YouTrack. Чтобы этого избежать, существует свойство Gradle kotlin.daemon.useFallbackStrategy, значение которого по умолчанию true. Когда значение равно false, сборки завершаются ошибкой при проблемах с запуском или взаимодействием демона. Объявите это свойство в gradle.properties:

kotlin.daemon.useFallbackStrategy=false

Также есть свойство useDaemonFallbackStrategy в задачах компиляции Kotlin, которое имеет приоритет над свойством Gradle, если вы используете оба.

tasks {
    compileKotlin {
        useDaemonFallbackStrategy.set(false)
    }   
}
tasks.named("compileKotlin").configure {
    useDaemonFallbackStrategy = false
}

Если памяти недостаточно для выполнения компиляции, в логах отобразится сообщение об этом.

Отчёты о сборке

Отчёты о сборке экспериментальны. Они могут быть удалены или изменены в любое время. Требуется опциональное включение (см. подробности ниже). Используйте их только для оценки. Мы ценим ваши отзывы об них на YouTrack.

Отчёты о сборках для отслеживания производительности компилятора доступны начиная с Kotlin 1.7.0. Отчёты содержат длительность различных этапов компиляции и причины, по которым компиляция не могла быть инкрементальной.

Используйте отчёты о сборках для изучения проблем с производительностью, когда время компиляции слишком велико или различается для одного и того же проекта.

Отчёты о сборке Kotlin помогают более эффективно изучить проблемы, чем Gradle build scans. Множество инженеров используют их для изучения производительности сборки, но единицей детализации в Gradle scans является отдельная задача Gradle.

Существует две распространённые ситуации, при решении которых анализ отчётов о сборке для длительных компиляций может быть полезен:

  • Сборка не была инкрементальной. Проанализируйте причины и исправьте лежащие в основе проблемы.

  • Сборка была инкрементальной, но заняла слишком много времени. Попробуйте переорганизовать исходные файлы — разделить большие файлы, сохранить отдельные классы в разных файлах, переработать большие классы, объявить функции верхнего уровня в разных файлах и так далее.

Узнайте как читать отчёты о сборке и как JetBrains использует отчёты о сборке.

Включение отчётов о сборке

Чтобы включить отчёты о сборке, укажите, где сохранить выходные данные отчёта о сборке в gradle.properties:

kotlin.build.report.output=file

Доступны следующие значения и их комбинации для вывода:

Вариант

Описание

file

Сохраняет отчёты о сборке в удобочитаемом формате в локальный файл. По умолчанию ${project_folder}/build/reports/kotlin-build/${project_name}-timestamp.txt

single_file

Сохраняет отчёты о сборке в формате объекта в указанный локальный файл

build_scan

Сохраняет отчёты о сборке в разделе custom values сводки о сборке. Обратите внимание, что плагин Gradle Enterprise ограничивает количество настраиваемых значений и их длину. В больших проектах некоторые значения могут быть потеряны

http

Отправляет отчёты о сборке с помощью HTTP(S). Метод POST отправляет метрики в формате JSON. Текущую версию отправляемых данных можно посмотреть в репозитории Kotlin. Примеры HTTP-конечных точек можно найти в этой статье в блоге

Полный список доступных вариантов для kotlin.build.report:

# Required outputs. Any combination is allowed
kotlin.build.report.output=file,single_file,http,build_scan

# Mandatory if single_file output is used. Where to put reports 
# Use instead of the deprecated `kotlin.internal.single.build.metrics.file` property
kotlin.build.report.single_file=some_filename

# Optional. Output directory for file-based reports. Default: build/reports/kotlin-build/
kotlin.build.report.file.output_dir=kotlin-reports

# Mandatory if HTTP output is used. Where to post HTTP(S)-based reports
kotlin.build.report.http.url=http://127.0.0.1:8080

# Optional. User and password if the HTTP endpoint requires authentication
kotlin.build.report.http.user=someUser
kotlin.build.report.http.password=somePassword

# Optional. Label for marking your build report (for example, debug parameters)
kotlin.build.report.label=some_label

Предел настраиваемых значений

Для сбора статистики о сводках о сборке отчёты о сборке Kotlin используют настраиваемые значения Gradle. И вы, и различные плагины Gradle можете записывать данные в настраиваемые значения. Количество настраиваемых значений ограничено. См. текущее максимальное количество настраиваемых значений в документации плагина сводки о сборке.

Если у вас большой проект, количество таких настраиваемых значений может быть довольно большим. Если это количество превышает предел, в логах может отобразиться следующее сообщение:

Maximum number of custom values (1,000) exceeded

Чтобы уменьшить количество настраиваемых значений, которые создаёт плагин Kotlin, вы можете использовать следующее свойство в gradle.properties:

kotlin.build.report.build_scan.custom_values_limit=500

Отключение сбора свойств проекта и системы

Логи HTTP-статистики сборки могут содержать некоторые свойства проекта и системы. Эти свойства могут изменять поведение сборок, поэтому их полезно регистрировать в статистике сборки. Эти свойства могут хранить конфиденциальные данные, например, пароли или полный путь к проекту.

Вы можете отключить сбор этой статистики, добавив свойство kotlin.build.report.http.verbose_environment в gradle.properties.

JetBrains не собирает эту статистику. Вы выбираете место для хранения ваших отчётов.

Что дальше?

Узнайте больше о:

  • Основы и особенности Gradle.

  • Поддержка вариантов плагинов Gradle.

Последнее изменение: 10 января 2023 г.
Параметры компилятора в плагине Kotlin Gradle Поддержка вариантов плагинов Gradle

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/gradle-compilation-and-caches.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API