Spec-Zone.ru › Kotlin 1.9

Компиляция и кэши в плагине 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 в качестве параметра командной строки.

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

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

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

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

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

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

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

kotlin.incremental.useClasspathSnapshot=false

Мы будем признательны за ваши отзывы об этой функции в YouTrack.

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

Точное резервное копирование выходных данных задач компиляции

Точное резервное копирование выходных данных задач компиляции Экспериментальное. Мы будем признательны за ваши отзывы об этом в YouTrack.

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

Включите эту оптимизацию, добавив свойство Gradle kotlin.compiler.preciseCompilationResultsBackup в файл gradle.properties:

kotlin.compiler.preciseCompilationResultsBackup=true

Пример использования точного резервного копирования в JetBrains

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

Comparison of full and precise backups

Первая и вторая диаграммы показывают, как использование точного резервного копирования в проекте Kotlin влияет на сборку плагина Kotlin Gradle:

  1. После внесения небольшого изменения ABI: добавление нового публичного метода в модуль, от которого зависят многие модули.

  2. После внесения небольшого изменения, не связанного с ABI: добавление приватной функции в модуль, от которого не зависят другие модули.

Третья диаграмма показывает, как точное резервное копирование в проекте Space влияет на сборку веб-фронта после небольшого изменения, не связанного с ABI: добавление приватной функции в модуль Kotlin/JS, от которого зависят многие модули.

Эти измерения были проведены на компьютере с процессором Apple M1 Max; на разных компьютерах результаты будут немного отличаться. Факторы, влияющие на производительность, включают, но не ограничиваются:

  • Насколько разогрет демон Kotlin и демон Gradle.

  • Насколько быстрым или медленным является диск.

  • Модель процессора и насколько он загружен.

  • Какие модули затронуты изменениями и насколько они велики.

  • Являются ли изменения ABI или нет.

Оценка оптимизаций с помощью отчетов о сборке

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

kotlin.build.report.output=file

Вот пример релевантной части отчета до включения точного резервного копирования:

Task ':kotlin-gradle-plugin:compileCommonKotlin' finished in 0.59 s <...> Time metrics: Total Gradle task time: 0.59 s Task action before worker execution: 0.24 s Backup output: 0.22 s // Pay attention to this number <...>

И вот пример релевантной части отчета после включения точного резервного копирования:

Task ':kotlin-gradle-plugin:compileCommonKotlin' finished in 0.46 s <...> Time metrics: Total Gradle task time: 0.46 s Task action before worker execution: 0.07 s Backup output: 0.05 s // The time has reduced Run compilation in Gradle worker: 0.32 s Clear jar cache: 0.00 s Precise backup output: 0.00 s // Related to precise backup Cleaning up the backup stash: 0.00 s // Related to precise backup <...>

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

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

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

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

Кэш конфигурации 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 Gradle execution stage, когда одна из задач компиляции 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

Если у Gradle-демона есть JVM-аргументы с 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 K2 находится в стадии Альфа. Он имеет базовую поддержку проектов Kotlin JVM, JS и Native.

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

Компилятор K2 станет стандартным по умолчанию начиная с Kotlin 2.0. Чтобы попробовать его в своих проектах сейчас и проверить производительность, используйте свойство Gradle kotlin.experimental.tryK2=true или выполните следующую команду:

./gradlew assemble -Pkotlin.experimental.tryK2=true

Это свойство Gradle автоматически устанавливает версию языка по умолчанию в 2.0 и обновляет отчёт о сборке количеством задач Kotlin, скомпилированных с помощью компилятора K2 по сравнению с текущим компилятором.

Отчёты о сборке пока не предоставляют информацию о задачах Kotlin/Native. Несмотря на это, мы всё равно рекомендуем использовать Kotlin 2.0 в качестве версии по умолчанию.

Узнайте больше о стабилизации компилятора K2 в нашем блоге Kotlin

END_OF_DOCUMENT_MARKER

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

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

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

Стратегия

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

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

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

Демон

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

Да

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

В процессе

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

Нет

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

Вне процесса

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

Нет

Самая медленная стратегия выполнения. Аналогична стратегии «В процессе», но дополнительно создает отдельный процесс Java внутри работника Gradle для каждой компиляции.

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

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

  • Свойство задачи compilerExecutionStrategy compile.

Свойство задачи 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
}

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

END_OF_DOCUMENT_MARKER

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

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

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

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

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

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

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

Отчёты о сборке также показывают версию Kotlin, используемую в проекте. Кроме того, начиная с Kotlin 1.9.0, вы можете увидеть, использовался ли текущий или компилятор K2 для компиляции кода в вашем Gradle build scan.

Узнайте как читать отчёты о сборке и о том, как 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

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

Опции, применимые только к HTTP:

# Mandatory. 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. Add a Git branch name of a build to a build report
kotlin.build.report.http.include_git_branch.name=true|false

# Optional. Add compiler arguments to a build report
# If a project contains many modules, its compiler arguments in the report can be very heavy and not that helpful
kotlin.build.report.include_compiler_arguments=true|false

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

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

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

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.

Последнее изменение: 24 июля 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