Donnez de l’amour à votre build, il vous le rendra ! ❤️

Louis Jacomet & Paul Merlin

Agenda

  • Qu’est-ce que Gradle ?

  • Fonctionnalités JVM

  • Logique de build

  • Structure de build(s)

  • Performance

  • Roadmap

Qui sommes nous ?

🧑‍💻 🧑‍💻

louis
speaker {
    name = "Louis Jacomet"
    company = "Gradle"
    joined = 2018
    position = "Support Team Lead"
    previously = "Dependency Management, JVM"
    past = listOf(
        "Terracotta / Ehcache" in 2013,
        "Devoxx Belgium Committee" in 2012,
        "Contractor" in 2002,
        "Java 'Hello, World!'" in 1997
    )
    failures = generateSequence(code) { bugs }
    twitter = "@ljacomet"
    github = "ljacomet"
    extra = "Not fully figured out how to stay out of management !?!"
}
paul
speaker {
    name = "Paul Merlin"
    company = "Gradle"
    joined = 2015
    position = "Configuration Cache Project Lead"
    previously = "Kotlin DSL Project Lead"
    successes = listOf(
        "BASIC 'Hello, World!'" in 1986,
        "C 'Hello, World!'" in 1989,
        "Java 'Hello, World!'" in 1996,
        "Kotlin 'Hello, World!'" in 2015,
        "tools", "daemons", "apps", "frameworks", "libs"
    )
    failures = generateSequence(code) { bugs }
    twitter = "@eskat0s"
    github = "eskatos"
}

Gradle

logo gradleware
logo gradle old
logo gradle elephant old

Depuis 2008, notre mission est d’accélérer la productivité des développeurs.

logo gradle elephant geometrics
logo gradle elephant
logo gradle elephant outline
logo gradle build tool

Outil de construction de logiciels publié sous la license Apache

C’est un des 20 projets open source les plus populaires d’après TechCrunch avec près de 30 millions de téléchargements mensuels.

logo gradle enterprise

Gradle Enterprise, produit commercial, est la première solution intégrée de Developer Productivity Engineering (DPE)

ge 1

Developer Productivity Engineering

DPE est une pratique logicielle émergente qui repose sur des technologies d’accélération et l’analyse de données pour améliorer la productivité des développeurs.

  • rendre les builds et tests plus rapides

  • rendre la recherche de problèmes plus efficace

Build Scans

Un enregistrement permanent
de ce qui se passe pendant un build.

buildscan example

build scan link

Gradle & Maven build speed challenge

qrcode build speed challenge

Recevez des goodies :)

On recrute !

Si ce dont nous allons parler aujourd’hui vous intéresse, venez travailler avec nous !

team map

Qu’est-ce que Gradle ?

🐘

Qu’est-ce que Gradle ?

Un outil pour automatiser la construction de logiciels

  • Un modèle de configuration extensible

  • Un moteur de résolution de dépendances

  • Un moteur d’exécution de tâches

Divers écosystèmes

Core

etc…​

Community

etc…​

Logos venant de Wikimedia ou des pages officielles™ respectives.

Comment on s’en sert ?

  • Gradle Wrapper

    • JVM requise, définit la version de gradle à utiliser, scripts pour utilisation sans installation

    • bootstrap: gradle-initializr.cleverapps.io ou une version de gradle installée

  • Utilisation

    • en ligne de commande

    • depuis un IDE

Démo

Comment on s’en sert ?

  • Gradle Wrapper [doc]

  • Utilisation en ligne de commande [doc]

  • Utilisation depuis un IDE
    [doc] IntelliJ IDEA
    [doc] vscode

Configuration extensible

  • Modèle de configuration extensible

  • Système de plugins

  • DSL dynamique

  • Modélisation d’un build vs. scripter des tâches

plugins {
    id("java")
}
java {
    withSourcesJar()
}
Diagram

build scan link

Comment ça marche ?

Diagram

Comment ça marche ?

Diagram

Résolution de dépendances

Commence par la tâche invoquée

Diagram

Résolution de dépendances

Puis connecte les tâches avec dépendance directe

Diagram

Résolution de dépendances

Et aussi celles indirectes, potentiellement dans un autre projet

Diagram

Exécution de tâches

Ne pas refaire ce qui a déjà été fait.

Faire ce qu’il y a à faire le plus vite possible

Diagram

Exécution de tâches

Ne pas refaire ce qui a déjà été fait

  • Build incrémental
    UP-TO-DATE

  • Build cache
    FROM-CACHE

  • Tâches incrémentales

Diagram

Exécution de tâches

Faire ce qu’il y a à faire le plus vite possible

  • Exécution parallèle des tâches

  • Exécution parallèle d’unités de travail
    Worker API / Test Execution

Diagram

Qu’est-ce que Gradle ?

Un outil pour automatiser la construction de logiciels

  • Un modèle de configuration extensible

  • Un moteur de résolution de dépendances

  • Un moteur d’exécution de tâches

Fonctionnalités JVM

Un peu de tout

  • Catalogues de version

  • Toolchains

  • Suites de tests

  • Tests fixtures

  • Publication

Catalogue de versions

  • Centralisation de la liste des dépendances

    • Coordonnées et version, y compris riche

    • Pas de classifier, exclude ou autres attributs

  • Accesseurs typés

  • Séparation : group:artifact et version

  • Groupes de dépendances

Démo

Format TOML

[versions]
groovy = "4.0.1"
lang = { strictly = "[3.8, 4.0[", prefer="3.9" } }

[libraries]
groovy-core = { module = "org.apache.groovy:groovy", version.ref = "groovy" }
groovy-json = { module = "org.apache.groovy:groovy-json", version.ref = "groovy" }
commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version.ref = "lang" }

[bundles]
groovy = ["groovy-core", "groovy-json", "groovy-nio"]

[plugins]
logging-capabilities = { id = "dev.jacomet.logging-capabilities", version = "0.10.0" }

Il existe aussi une API dans le fichier settings de Gradle.

Points d’attention

  • Contrainte comme une autre

    • N’impose pas une version

    • Supporte les options riches

  • Publication et import de catalogue

  • Limitations

    • Pas pour un plugin de settings

    • Ni script d’initialisation

Java Toolchains

  • Séparation du Java pour Gradle et de celui pour le projet

  • Application pour la compilation, les tests et l’exécution

  • Critères disponibles :

    • Version du langage Java

    • Vendeur de la JVM

    • (Implémentation : défaut ou J9)

Démo

Quel Java Gradle connait-il?

  • Défauts autodétectés :

    • Par OS: Linux, macOS, Windows

    • Package managers: Asdf-vm, Jabba, SDKMAN!

    • Maven toolchains

    • Téléchargements précédents

  • Explicite

Provisioner Java

  • Possible grâce à AdoptOpenJDK

  • Mais pas idéal, suite à la migration Adoptium

  • Micmac avec le vendeur

Futur

  • SPI pour créer des plugins de provisionnement

  • Plus d’options pour sélectionner sa JVM

    • GraalVM, version plus précise, early access, …​

  • Support dans plus de tâches

    • Core Gradle : analyse de code par exemple

    • Plugins de la communauté : demandez le support !

Les suites de tests

  • Modélise une collection de tests

  • Séparation logique des tests au niveau des sources et dépendances

  • Défaut de Gradle, test, est dérivé de ce modèle

Démo

Evolution des suites de tests

  • Notions de dimensions

    • Différentes versions de Java pour tourner les tests

    • Produira plusieurs tâches de Test

  • Intégration avec la couverture de code

    • Interaction au niveau de la tâche actuellement

Test fixtures

  • Séparation des fixtures du code de test

  • Consommation des fixtures d’une librairie

  • Illustration du modèle avancé de gestion de dépendances de Gradle

Démo

Modélisation des tests fixtures

  • Comme les suites de test : sources et dépendances séparées

  • Publication complète

    • Variante dans Gradle Module Metadata

    • classifier pour Maven / Ivy

Gestion de dépendances : les variantes

  • Dimension supplémentaire d’un composant logiciel

  • Peut avoir ses propres artifacts et dépendances

  • Pensez classifier, sans les limitations

  • Nécessite Gradle Module Metadata (GMM)

Autre exemple : Dépendances optionelles

  • Définition d’une variante qui

    • Dépend du composant principal

    • Ajoute des dépendances

    • Peut aussi ajouter un binaire

  • Dépendances en fait pas optionelles …​

  • Mais obligatoires pour certaines fonctionnalités

Exemple

producer.gradle.kts
java {
    registerFeature("mysqlSupport") {
        usingSourceSet(sourceSets["main"])
    }
    registerFeature("mongodbSupport") {
        usingSourceSet(sourceSets["main"])
    }
}

dependencies {
    "mysqlSupportImplementation"("mysql:mysql-connector-java:8.0.14")
    "mongodbSupportImplementation"("org.mongodb:mongodb-driver-sync:3.9.1")
}
consumer.gradle.kts
dependencies {
    implementation(project(":producer"))

    // On ajoute la variant MySQL
    runtimeOnly(project(":producer")) {
        capabilities {
            requireCapability("org.gradle.demo:producer-mysql-support")
        }
    }
}

Applications du modèle des variantes

  • Test fixtures

  • Fonctionalités optionelles

  • Aggregation de résultats entre projets

  • (Transformation d’artifacts)

Publication

  • Que publie-t-on ?

    • Un composant

    • Ses variantes

    • Ses meta données

  • Où le publie-t-on ?

    • Dans un repository Maven ou Ivy

  • Comment publier ?

Démo

Que publier ?

  • Le composant

    • Modélisation d’un ensemble de variantes

    • Variante: configuration consommable et artifacts

    • java pour les plugins Java

  • Modifiez le composant plutôt que la publication

    • Un artifact additionnel ?

    • Définissez une variante

Méta données

  • Pas d’API de manipulation des GMM

  • Mutation de POM avec withXml ⇒ différences

  • Comme pour les artifacts, modifiez le composant !

Astuces de publication

Besoins pour les composants JVM

Beaucoup de choses incluses …​

... Mais tout n’est pas couvert

Qu’est-ce qu’il vous manque en pratique?

Pensez à le demander ici, à la BoF jeudi ou sur GitHub

Fonctionnalités JVM

  • Catalogues de version

  • Toolchains

  • Suites de tests

  • Tests fixtures

  • Publication

Logique de build

🧰

Composants de base

  • Un fichier de configuration du build: settings.gradle(.kts)

  • Un fichier de configuration par projet: build.gradle(.kts)

  • Des fichiers annexes:

    • gradle.properties

    • gradle/wrapper

    • Catalogues de version *.versions.toml

    • Et plus …​

Langages d’implémentation

Diagram

Scripts du build vs. Plugins

Configuration
Les scripts du build sont déclaratifs

Conventions
Les plugins locaux au build implémentent la logique de configuration du build

plugins.gradle.org
La logique de build utilise des plugins externes

Écrire des plugins

Un plugin Gradle est construit par un build Gradle

Des plugins de développement de plugins pour:

  • modéliser la construction de plugins Gradle

  • valider plugins, extensions de DSL et tâches

  • faciliter les tests d’intégration

  • déclarer les métadonnées des plugins

  • publier les plugins sur plugins.gradle.org

Script d’un projet de plugin Java
plugins {
    id("java-gradle-plugin")
}
Script d’un projet de plugin Groovy
plugins {
    id("groovy-gradle-plugin")
}
Script d’un projet de plugin Kotlin
plugins {
    id("kotlin-dsl")
}

Modèle de programmation

Don’t call us, we’ll call you!
Sugarloaf^WHollywood

Types abstraits, instanciés et décorés
par Gradle

Services Gradle injectés

Something.groovy
abstract class Something implements GradleApiType {

    @Inject
    abstract ExecOperations getExecOps()

    abstract Property<String> getSomeProperty()

    @Override
    def someAction() {
        execOps.exec {
            commandLine "git", "status"
        }
        println someProperty.get()
    }
}
build.gradle
def some = objects.newInstance(Something)

Beans ?

Oui et non …​ JavaBeans + Property<T>

JavaBeans pour l’interop avec Groovy et Kotlin

Property<T> est un conteneur de valeur
Provider<T> est son pendant immutable

  • associe une propriété à ses dépendances dans le build

  • permet un chaînage lazy des propriétés

Blocs de construction

Plugins

Extensions de DSL

Tâches

Diagram

Phases d’un build

Configuration
Plugins + DSL = enregistrement des tâches

Calcul du graphe de tâches
Gradle

Execution du travail
Dépendances de tâches, incrémentalité

Plugins

Cibles de plugin

  • Project

  • Settings

  • Gradle

Equivalences en scripts

  • project script

  • settings script

  • init script

MyPlugin.java
class MyPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        /* ... Utilisation de l'API Gradle ... */
    }
}

Scripts de plugin précompilés

aka. Precompiled Script Plugins

Plugins écrits avec le DSL gradle

Placés dans un SourceSet

src/main/kotlin/my-plugin.gradle.kts
src/main/kotlin/my-plugin.settings.gradle.kts
src/main/groovy/my-plugin.init.gradle

Étendre le DSL

Extensions : objets nommés
enregistrés sur Settings ou Project

MyExtension.kt
interface MyExtension {

    var someProperty: Property<Int>

    var someDirectory: DirectoryProperty

    fun someFunction(parameter:String)
}
my-plugin.gradle.kts
extensions.create<MyExtension>("myExtension")
build.gradle
plugins {
    id("my-plugin")
}

myExtension {
    someProperty = 42
    someDirectory = layout.buildDirectory.dir("pa/th")
    someFunction("parameter")
}

Démo

Écrire des tâches

Les tâches sont des fonctions

Que sont les input de la tâche ?

Que sont les outputs de la tâche ?

Que se passe-t-il quand l’un d’eux change ?

Diagram

Test d’incrémentalité

  • Lancer un build

  • Lancer un autre build sans faire de changement

  • Les tâches doivent être UP-TO-DATE

Test de mise en cache

  • Activer le build cache

  • Préparer deux copies du même projet dans des répertoires différents

  • Dans le premier répertoire, lancer un build

  • Dans le deuxième répertoire, lancer un build

  • Les tâches du deuxième build doivent être FROM-CACHE

Écrire des tâches

Exécutée à chaque fois

MyTask.kt
abstract class MyTask : DefaultTask() {

  abstract val inputs: ConfigurableFileTree

  abstract val output: DirectoryProperty

  @TaskAction
  fun action() {
    /* ... */
  }
}

UP-TO-DATE

MyTask.kt
abstract class MyTask : DefaultTask() {

  @get:InputFiles (1)
  abstract val inputs: ConfigurableFileTree

  @get:OutputDirectory (2)
  abstract val output: DirectoryProperty

  @TaskAction
  fun action() {
    /* ... */
  }
}
1Déclare cette propriété comme un input
2Déclare cette propriété comme un output

Tâches mises en cache

MyTask.kt
@CacheableTask (1)
abstract class MyTask : DefaultTask() {

  @get:InputFiles
  @get:PathSensitive(RELATIVE) (2)
  abstract val inputs: ConfigurableFileCollection

  @get:OutputDirectory
  abstract val output: DirectoryProperty

  @TaskAction
  fun action() {
    /* ... */
  }
}
1Marque la tâche comme cacheable
2Définit la sensibilité des chemins pour cet input

Inputs de tâches incrémentaux

MyTask.kt
fun action(inputChanges: InputChanges) {
  /* ... */
}

Sachez précisemment quels fichiers ont changé

L’action de tâche peut alors faire le minimum de travail

Usage typique : produire un fichier output par fichier input

Usage avancé : compilation

Démo

Écrire des tâches

Beaucoup d’opt-ins auxquels penser

Gradle valide les plugins et les tâches

  • au runtime → warnings / failures / deprecations

  • lors de l’écriture de plugins → :validatePlugins

Évolution balancée vers plus de choses par défaut tout en maintenant la compatibilité

Tester c’est douter

Tests unitaires
ProjectBuilder [doc]

Tests d’intégration
Gradle TestKit [doc]

tester cest douter

Tests unitaires

ProjectBuilder

Pour tester les interactions avec le modèle de configuration

Seulement sur Project

Pas pour tester les tâches

Tests d’intégration

Gradle TestKit

Pour tester des builds complets

Fait tourner un vrai Gradle

Expose la sortie de Gradle et les résultats de tâche pour assertions

Démo

Supporter plusieurs versions de Gradle

Tester plusieurs versions de Gradle

  • Pas de support intégré dans Gradle

  • S’implemente relativement facilement

Supporter plusieurs versions de Gradle

Tester plusieurs versions de Gradle

build.gradle.kts
listOf("5.0", "6.0", "7.0", "7.4.2").forEach { testedVersion -> (1)
    val taskName = "testGradle${testedVersion.replace(".","_")}"
    val testTask = tasks.register<Test>(taskName) {
        classpath = tasks.test.get().classpath
        /* ... */
        systemProperty("testedGradleVersion", testedVersion) (2)
    }
    tasks.check { dependsOn(testTask) }
}
1Liste des versions de Gradle testées
2Une System Property que les tests peuvent utiliser
AbstractIntegrationTest.kt
GradleRunner.create().withGradleVersion(System.getProperty("testedGradleVersion"))

Support officiel futur grâce aux tests matriciels

Structure de build(s)

🗃

Un ou plusieurs projets

  • Un seul build contient un ou plusieurs projets

  • Les settings servent à

    • déclarer les participants à un build

    • configurer des éléments communs

  • Tâche projects pour lister les participants d’un build

Démo

Structure d’un build

  • Approcher celle-ci comme celle de n’import quel code

    • Eviter les répetitions

    • Construire des abstractions

    • En bref, appliquer des bonnes pratiques !

  • Mais pensez à votre futur moi

    • Ouvrir un projet doit vous donner les informations importantes

    • Trop de centralisation peut nuire la relecture

Démo

Plugins de convention

  • Orchestration de plugins existants

  • Configuration de défauts pour vous, votre projet, votre compagnie

  • Au sein du projet ou publiés

La convention buildSrc

  • Contient du code visible pour la configuration du projet

  • Tous les projets voient tout le contenu de buildSrc

  • Tout changement invalide tous les projets

Composition de builds

  • Mélanger plusieurs builds indépendants

  • Un build principal et un ou plusieurs builds inclus

  • Gradle s’occupe de connecter les morceaux

  • Remplace une publication locale

Démo

Composition pour logique de build

  • Même principe qu’un composite classique

  • Le build contribue de la logique …​ de build

  • Plus ciblé que buildSrc

Démo

Mono vs. Multi repository

  • Décision qui vous appartient

  • Gradle est agnostique à cette notion

  • Dans les deux cas, vous pouvez avoir plusieurs builds

  • Assemblés en tant que composites

Performance

🚀

Performance

xkcd compiling

Performance

monkeyuser focus

Un build rapide c’est

Moins de temps d’attente

Moins de changements de contexte

Plus de fluidité dans notre travail

Mesurer c’est douter

  • Mesurer

  • Changer

  • Mesurer

  • Comparer

Build Scans

Un enregistrement permanent de ce qui se passe pendant un build

buildscan example
build scan link

gradle-profiler

  • Installer avec SDKMAN! ou Homebrew
    ou télécharger depuis GitHub

  • Orchestre des builds Gradle pour
    mesurer, changer, mesurer, comparer

  • Scenarios avec mutations pour
    builds, synchronisation IDE

  • Benchmarks & comparaisons

  • Profilers
    async-profiler, jprofiler, yourkit, jfr

gradle-profiler

Scenarios

performance.scenario
upToDateBuild {
  tasks = ["assemble"] (1)
}
cleanBuild {
  tasks = ["assemble"]
  cleanup-tasks = ["clean"] (2)
}
nonAbiChange {
  tasks = ["assemble"]
  apply-non-abi-change-to = ["src/main/java/MyThing.java", "src/main/java/MyOtherThing.java"] (3)
}
compareGradle {
  tasks = ["assemble"]
  versions = ["7.0", "7.4.2"] (4)
}
1Chaque exécution lancera les taches declarées
2Taches exécutées et non mesurées entre exécutions
3Une collection de modifieurs pour changer des fichiers entre exécutions
4Comparaison de versions de Gradle
Et bien plus encore …​

gradle-profiler

Benchmark & comparaison

profiler benchmark results html
Résultats en HTML et en CSV

gradle-profiler

Profiling avec async-profiler

gradle-profiler

  • Scenarios fréquents pour vos developpeurs / CI

    • Temps de configuration

    • Build incrémental

    • Synchronisation IDE

  • Benchmarks récurrents pour prévenir les regressions

  • Profiling pour identifier les bottlenecks

Elements de la performance Gradle

  • Construction parallèle

  • Résolution de dépendances

  • Gestion de la mémoire

Construction parallèle

Nombre de workers

Définit le maximum de travaux exécutés en parallèle

Par défault == nombre de cores

En ligne de commande
./gradlew --max-workers=16
gradle.properties
org.gradle.workers-max=16
--max-workers=1 pour un build séquentiel
Diagram

Construction parallèle

Deux choses sont exécutés en parallèle par défaut

  • Téléchargement des dépendances

  • Tâches utilisant la Worker API

Diagram

Construction parallèle

Exécution de tâches en parallèle

En ligne de commande
./gradlew --parallel
gradle.properties
org.gradle.parallel=true

Seulement entre tâches de différents projets
Les tâches d’un même projet sont exécutés séquentiellement

Pas de contrat d’isolation des unités de travail !

Problèmes possibles si

  • mauvaise déclaration des inputs et outputs de tâches

  • logique de tâches qui accède à des tâches d’autre projets

En pratique, Core est testé, la vaste majorité des plugins le supportent.

Construction parallèle

Exécution des tests en parallèle

Si une tâche de test est trop longue elle empêche d’autres workers d’exécuter d’autres tâches.

build.gradle.kts
tasks.test {
    maxParallelForks = 16 (1)
    forkEvery = 100 (2)
}
1Définit le nombre maximum de workers utilisés pour l’exécution des tests
2Nombre maximum de tests exécutés par un processus d’exécution de test

Construction parallèle

  • Parallélisme maximum --max-workers=16

  • Téléchargement des dépendances

  • Tâches utilisant la Worker API

  • Parallélisme entre projets --parallel

  • Parallélisme des tests
    tasks.test { maxParallelForks = 16 }

Diagram

Résolution de dépendances

Versions dynamiques - qui changent dans le temps

build.gradle.kts
dependencies {
    implementation("org.springframework:spring-web:5.+") (1)
    implementation("org.springframework:spring-web:5.0.3.BUILD-SNAPSHOT") (2)
}
1Nécessite de lister les versions disponibles
2Nécessite de résoudre le dernier SNAPSHOT

Vérifier si une nouvelle version est disponible peut avoir un fort impact sur les performances.

Résolution de dépendances

Déclarations de repositories

Chaque dépendance est cherchée dans les repositories dans leur ordre de déclaration.

build.gradle.kts
repositories {
    mavenLocal() (1)
    mavenCentral() (2)
    maven { url = uri("https://repo.mycompany.com") } (3)
}
1L’accès à ~/.m2/repository n’est pas coordonné (besoin de "toucher le disque" à chaque build) et les snapshots ne sont pas datés (confiance zero)
2Les dépendances internes vont être cherchées sur Maven Central
3Le repository interne va recevoir des reqûetes pour les dépendances non trouvées

Résolution de dépendances

Déclarations de repositories

build.gradle.kts
repositories {
    maven {
        url = uri("https://repo.mycompany.com")
        content {
            includeGroup("my.company") (1)
        }
    }
    mavenCentral {
        content {
            excludeGroupByRegex("my\\.company.*") (2)
        }
    }
    mavenLocal {
        content {
            includeGroup("my.company") (3)
        }
    }
}
1Ce repository ne sera utilisé que pour des dépendances avec le groupe my.company
2Ce repository ne sera utilisé pour tout sauf les dépendances avec le groupe my.company
3mavenLocal() est mis en dernier et filtré pour éviter de "toucher le disque" trop souvent ou des incohérence de dépendances.
Ne pas en avoir besoin c’est mieux !

Gestion de la mémoire

Un build c’est au minimum deux processus Java
avec des paramètres mémoire par défaut

Gradle Client
UI (CLI/IDE) et communication avec le daemon
-Xmx64m

Gradle Daemon
Configure et exécute le build
-Xmx512m -XX:MaxMetaspaceSize=256m

Certaines tâches utilisent d'autres processus
-Xmx512m -XX:MaxMetaspaceSize=256m

Gestion de la mémoire

Comprendre qu’on a un problème mémoire

  • Build trop lent

  • Expiring Daemon because JVM heap space is exhausted

  • Les Build Scans montrent la pression mémoire build scan link

  • gradle-profiler pour capturer les allocations

Gestion de la mémoire

Changer les paramètres mémoire

Gradle CLI - rarement nécessaire
Variable d’environnement JAVA_OPTS
JAVA_OPTS="-Xmx64m -XX:MaxPermSize=64m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
Gradle Daemon
gradle.properties
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
Tâches, e.g. Test
build.gradle.kts
tasks.test {
    maxHeapSize = "1G"
}

Nouvelles fonctionnalités

Configuration Cache [incubating]
Cache le résultat de la configuration et du calcul du graphe de tâches, et réutilise pour les builds suivants.

Project Isolation [prototype]
Étend le cache de configuration pour accélérer la phase configuration et la synchronisation depuis un IDE.

Configuration Cache

Principes

  • Cache le résultat de la configuration et du calcul du graphe de tâches, et réutilise pour les builds suivants.

  • Détection des inputs de la logique de build pour invalidation

  • Tâches isolées du modèle de build mutable et entre elles

Configuration Cache

Bénéfices

  • Quand rien n’a changé, la configuration est complétement sautée

  • Moins de pression mémoire car le modèle de build peut être garbage collecté

  • Exécution de toutes les tâches en parallèle (incl. intra-projets)

Configuration Cache

cc perf java

Configuration Cache

cc perf android

Démo

Configuration Cache

Contraintes sur la logique de configuration

  • Environnement, fichiers de conf, process externes (e.g. git) etc…​

  • Build listeners enregistrés lors de la configuration, notifiés lors de l’exécution

  • configuration_cache#requirements

Configuration Cache

Contraintes sur la logique d’exécution

  • Pas de références au modèle de build dans les tâches
    e.g. Project, Task etc…​

  • Pas d’objets live dans les inputs
    e.g. InputStream, Socket etc…​

  • configuration_cache#requirements

Démo

Configuration Cache

Force les bonnes pratiques

  • Claire séparation entre configuration et execution

  • Déclaration correcte des inputs

  • Pas d’interdépendance entre instances de tâches

Configuration Cache

Les plugins Core JVM sont compatibles
tous les autres ne le sont pas encore [doc]

Les plugins Kotlin et Android sont compatibles

De plus en plus de plugins communautaires sont compatibles gradle/gradle#13490

Configuration Cache

Feuille de route, à ce jour

  • incubating ⇒ stable dans Gradle 8.x
    (en opt-in)

  • Activé par défaut dans Gradle 9.0
    (avec un opt-out)

  • Seul mode possible dans Gradle x.x
    (sans opt-out)

Configuration Cache

Cache le résultat de la configuration et du calcul du graphe de tâches, et réutilise pour les builds suivants.

Le jeu en vaut la chandelle

Vous pouvez démarrer son adoption dès aujourd’hui

Project Isolation

Principes

  • Étend le cache de configuration pour accélérer la phase configuration et la synchronisation depuis un IDE.

  • Isole les projets les uns des autres

Project Isolation

Bénéfices

  • Synchronization IDE plus rapide

    • Cache de modèles TAPI pour les IDE

  • Phase de configuration plus rapide

    • Cache de configuration par projet

    • Configuration parallèle

Project Isolation

Contraintes

  • Ne pas référencer un Project depuis un autre

  • Configuration avec subprojects {} & allprojects {}

    • Utiliser des plugins de convention

  • Consommer les outputs d’un projet dans un autre

    • Utiliser les publications et les dépendances

Project Isolation

État d’avancement

Actuellement au stade de prototype

Activable aujourd’hui

  • dégrade les performances si les contraintes sont violées

  • l’accéleration de la synchronization IDE ne fonctionne pas encore

  • l’accéleration de la phase de configuration n’est pas implémentée

Performance

  • Mesurer

  • Changer

  • Mesurer

  • Comparer

Roadmap

📃

Principales priorités

  • Écosystème JVM

  • Idiomatic Gradle

  • Performance

Écosystème JVM

Focus actuel

  • Aggregation de résultats

  • Diagnotics de résolution de dépendances

  • Java 18 et 19

  • Toolchains

    • Checkstyle

Focus suivant

  • Toolchains

    • SPI

    • Selection de JVM

    • Exploitation core et plugins

  • Test suites

    • Matrices de tests

    • Couverture du code

Idiomatic Gradle

Focus actuel

  • Build continu sur base de notifications du systeme de fichiers

  • Groovy 4 & Kotlin 1.6

Focus suivant

  • Migration complète vers Property<T>

  • Uniformité des DSL Groovy et Kotlin

  • Tester plusieurs versions de Gradle

Performance

Focus actuel

  • Configuration Cache
    stable

  • Project Isolation
    incubating

Focus suivant

  • Project Isolation
    stable

On recrute !

Si ce dont nous avons parlé aujourd’hui vous intéresse, venez travailler avec nous !

team map

Questions

folks

Merci !

🙇

folks

JOOQ, joy of SQL
Jeudi 10h45, Kevin Davin

Gradle BoF
Jeudi 21h, Kevin, Louis, Paul