allegro / axion-release-plugin

Gradle release & version management plugin.
https://axion-release-plugin.readthedocs.io/
Apache License 2.0
545 stars 147 forks source link

Retrieving the version for large repositories is slow #736

Closed balrok closed 1 week ago

balrok commented 1 week ago

When following the recommended way to set the version in a gradle project:

project.version = scmVersion.version

it can take a considerable amount of time to compute it for larger projects.

How to reproduce (real project)

+def start = System.currentTimeMillis(); +scmVersion.version +println("Took " + ((System.currentTimeMillis() - start) / 1000) + "s") + ext { moduleProjects = subprojects.findAll { it.name.startsWith("spring-") } javaProjects = subprojects.findAll { !it.name.startsWith("framework-") }

* spring-framework uses a version-scheme for its tags which are not like it is configured in the plugin. Since they do not seem to have an influence on the speed, simply delete them `git tag -d $(git tag)` or configure the plugin, that it works
* run `./gradlew cV` and watch out for the "Took Xs"

### Measurements:
* directly after cloning:
    * 0.5s - 2.0s
* adding 10k files: `for i in $(git ls-files|grep -v "/$"); do touch "$i.release-plugin-test"; done`
    * 1.5s - 3.5s
* adding 30k commits: `for i in $(seq 1 30000); do git commit --allow-empty -m"$i"; done`
    * 1.4s - 3.4s

## How to reproduce (real project)

Alternatively, one can create an empty git project with only build.gradle:
```gradle

plugins {
    id 'pl.allegro.tech.build.axion-release' version '1.17.0'
}

def start = System.currentTimeMillis();
scmVersion.version
println("Took " + ((System.currentTimeMillis() - start) / 1000) + "s")

Measurements:

Why is it important?

The current version is calculated with each execution of gradle. This means, that it also runs for each test-execution from the ide. Also my examples here don't paint the full picture: for a different project it takes 20s on my machine. Due to gradles build-directories and maybe some other random things, I have 600k files.

Proposed solutions

I think most of the time is spent in computing things, which are not always important:

bgalek commented 1 week ago

hi! sure, feel free to make a PR with those improvements.

balrok commented 1 week ago

Just found there is also a related issue: #182 (just referencing it in case somebody stumbles over the other)

For the performance-problem with getting the tags I figured out a different optimization: if the tags are stored inside .git/packed-refs, they are resolved super fast with jgit. If this file doesn't exist yet, it can be created with git gc --aggressive --prune (warning: not sure if it can do any harm, so one might backup the .git-folder before).

Together with the overridenIsClean flag I get the scmVersion.version-calculation down to 0.064s from initially 18s.