Skip to content

Timestamp fingerprinting is slow for large glob patterns (e.g. **/*.gql) #2746

Closed

Description

@ItaiYosephi

Description

When using method: timestamp with glob patterns like **/*.gql that match thousands of files across a large directory tree, the fingerprinting step is significantly slower than expected (~6.6s for ~5000 matching files in a monorepo).

What did you do?

Created a task with method: timestamp and source globs like:

sources:
  - /path/to/monorepo/schema/**/*.gql
  - /path/to/monorepo/app/src/**/*.gql
  - /path/to/monorepo/app/scripts/codegen/**/*
generates:
  - /tmp/output.txt

What did you expect to happen?

The up-to-date check should be fast since it only needs to compare file modification times.

What happened instead?

The check takes ~6.6s because:

  1. Globs() uses execext.ExpandFields which shells out to expand glob patterns into a complete file list before any timestamp comparison. For **/*.gql patterns matching thousands of files, this is very expensive (~2.7s per call).

  2. Value() is called redundantly: In compiledTask() (variables.go:184), the Value() call is not gated by evaluateShVars. Since RunTask calls both FastCompiledTask and CompiledTask sequentially (task.go:142 and task.go:159), Value() runs twice — adding ~2.7s of unnecessary overhead.

  3. No short-circuiting in IsUpToDate: All globs are fully expanded into a file list before any timestamp comparison begins. For the common "up-to-date" case, this means stating every single matching file even though only one newer file would be enough to decide.

Version

Latest main (commit 54bdcba)

Operating system

macOS (Darwin 25.3.0), but the issue is platform-independent — it affects any large directory tree with ** glob patterns.

Activity

  1. trulede commented on Mar 22, 2026

    @trulede
    Contributor

    The succinct problem is, essentially (and because) files normally don't change in your example, that you want to reliably detect 1 changed file out of 5000 when often the are actually no changed files. This means, statistically, that most often you would have to scan a large portion of the files for a single change (50%), and if normally you don't expect files to change, actually you would have to scan all the files every time (100%).

    To do that Task will have to glob all those files, and then compare the timestamps of each. The call to value() might be redundant, in some cases, and I believe there is a more generic strategy to deal with that - but its a longer term adjustment.

    So, returning to the original (succinct) problem. You could possibly use a status command to check if any file has changed, that would prevent the unnecessary globing in most cases. Try a command like this, and see if it is significantly faster than Task. That would establish a useful benchmark.

    find /your/directory -type f -name "*.txt" -newermt "2024-01-01"

    With that benchmark you can determine if a status command would be of benefit.

  2. added theissue type on Mar 22, 2026
  3. added
    area: fingerprintingChanges related to checksums and caching.
    and removed
    state: needs triageWaiting to be triaged by a maintainer.
    on Mar 22, 2026
  4. trulede commented on Apr 13, 2026

    @trulede
    Contributor

    @ItaiYosephi do you have any more feedback. Otherwise I would close the issue with a suggestion to use a status command to bypass the task mechanism, especially if you don't expect files to change.

  5. self-assigned this
    on Apr 13, 2026
  6. trulede commented on Apr 18, 2026

    @trulede
    Contributor

    I suggest to use either find or git to detect changes files, configuring the commands in Task with if or preconditions. If that is faster, then great! At least when no files have changed, you should avoid the overhead of Tasks mechanism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Fields

No fields configured for support.

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions