Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

`targetExclude("**/build/**")` makes configuration cache store and reuse walk the entire project directory

Đang mở
#3,147 0 bình luận 1 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
43/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
java, kotlin
Lĩnh vực
build-system, performance

Hướng nghiên cứu

Start with FormatExtension.java around lines 314 and 329, then trace target subtraction and the lineEndingsPolicy input around lines 1096 and 1114. Read GitAttributesLineEndings.java around line 92 and inspect the supplied configuration cache stack trace to understand when the file tree is traversed. Done means string targetExclude("**/build/**") avoids walking and fingerprinting unrelated project files during configuration cache store and reuse while preserving the exclusion behavior; the issue provides TestKit timing comparisons to reproduce and assess the change.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug
Summary

A targetExclude string pattern that starts with ** makes configuration-cache store and reuse scale with the total number of files under the project directory. This happens even when target is already scoped to a few subfolders, as recommended in #2717 and #833.

spotless {
    kotlin {
        ktlint()
        target(
            "build-logic/**/*.kt",
            "build-logic/**/*.kts",
            "settings-logic/**/*.kt",
            "settings-logic/**/*.kts",
        )
        targetExclude("**/build/**")
    }
}

Measured with TestKit, Gradle 9.8.1, project dir containing ~100k unrelated files, spotlessKotlinCheck --dry-run:

Configuration CC store CC reuse
target(...) only ~70 ms ~50 ms
target(...) + targetExclude("**/build/**") ~1000 ms ~1250 ms
target(fileTree(".") { include(...); exclude("**/build/**") }) ~90 ms ~45 ms

With --no-configuration-cache all three configurations take under 100 ms at configuration time. In a real repo the walk covers .git, .gradle and every module's build output, so the cost grows with the size of the repo.

Root cause
  1. A string targetExclude becomes project.fileTree(projectDir).include("**/build/**") (FormatExtension.java:314). Gradle cannot prune a leading **, and the exclude branch returns before the default .git / .gradle / build-dir excludes are added (L329). So resolving this tree means walking the whole project directory.
  2. The task target is target.minus(targetExclude) (L1096).
  3. With the default GIT_ATTRIBUTES_FAST_ALLSAME, the lineEndingsPolicy task input is LazyAllTheSame (L1114). When the configuration cache serializes that input, LazyForwardingEquality.writeObject calls calculateState(), which runs toFormat.get().iterator() (GitAttributesLineEndings.java:92) just to get the first file. Iterating the SubtractingFileCollection resolves right.getFiles(), which walks the whole tree.
  4. Because this happens during configuration, Gradle records the collection as a configuration input (ConfigurationCacheFingerprintWriter.fileCollectionObserved) and snapshots the whole tree. On every later build the fingerprint check snapshots it again, so CC reuse is slow too.

Relevant stack excerpt from the store phase:

at org.gradle.internal.cc.impl.fingerprint.ConfigurationCacheFingerprintWriter.fileCollectionObserved
at org.gradle.api.internal.file.collections.DefaultConfigurableFileTree.getFiles
...
at com.diffplug.spotless.extra.GitAttributesLineEndings$LazyAllTheSame.calculateState
at com.diffplug.spotless.LazyForwardingEquality.state
at com.diffplug.spotless.LazyForwardingEquality.writeObject
at org.gradle.internal.serialize.codecs.core.jos.JavaObjectSerializationCodec$WriteObjectEncoding.encode
at org.gradle.internal.serialize.codecs.core.ProviderCodec.encode
at org.gradle.internal.serialize.codecs.core.TaskNodeCodec.writeTask

Replacing minus with filter { !targetExclude.contains(it) } is not enough: it only brings store to ~350 ms and reuse to ~640 ms. DefaultConfigurableFileTree.contains() also reports fileCollectionObserved during configuration, so the whole exclude tree still gets fingerprinted.

Related to

  • #833
  • #2717
Ngôn ngữ chính
Java
Star
5.7k
Fork
562
Merge trung bình
3 ngày 2 giờ
Pull request đã merge (30 ngày)
14

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của diffplug/spotless

Tất cả issue của diffplug/spotless

Issue tương tự

Thêm issue về Java

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.