Skip to content

mcpp run recursively scans large submodules despite explicit source glob #225

Description

@Sunrisepeak

Summary

mcpp run performs a full recursive filesystem scan of large unrelated directories before running a cached root package. With large Git submodules under the repository root, this adds approximately 9.5 seconds to every invocation, even when no compilation is required.

This is especially visible for repositories that keep upstream test corpora or benchmarks as submodules under compat/.

Environment

  • mcpp: 0.0.93
  • host: Linux x86_64
  • toolchain: GCC 16.1.0
  • project: source-only C++26 workspace/package
  • root package source pattern inferred by mcpp: src/**/*.{cppm,cpp,cc,c}

The project has large read-only Git submodules which are not package sources:

compat/bun
compat/node

The root package sources are only under:

src/

Reproduction

From the project root:

/usr/bin/time -f 'real=%e user=%U sys=%S' mcpp run -- --version
/usr/bin/time -f 'real=%e user=%U sys=%S' mcpp run -- --version

Observed:

Finished release [optimized] in 0.03s
Running target/.../mbun
1.3.14
real=9.57 user=4.55 sys=4.99

Finished release [optimized] in 0.03s
Running target/.../mbun
1.3.14
real=9.50 user=4.61 sys=4.86

The same binary does not have this startup cost:

/usr/bin/time -f 'real=%e user=%U sys=%S' target/.../mbun --version

Observed:

1.3.14
real=0.00 user=0.00 sys=0.00

A regular cached build is also fast:

/usr/bin/time -f 'real=%e user=%U sys=%S' mcpp build

Observed:

Finished release [optimized] in 0.02s
real=0.04 user=0.03 sys=0.01

Filesystem evidence

Tracing only file-related syscalls for mcpp run for 15 seconds produced approximately 1,434,120 file operations before timeout. The paths were dominated by unrelated submodules:

compat/node  377,254 path references
compat/bun   133,626 path references
compat       67,084 path references
.mcpp/.xlings 44,676 path references

The command used was:

timeout 15s strace -f -qq -e trace=file \\
  -o /tmp/mcpp-files.strace \\
  mcpp run -- --version

Process tracing also showed that mcpp only probes the compiler at the beginning (g++ --version, -dumpmachine, -print-sysroot). It does not start a real compile or the mbun binary during the long delay.

Expected behavior

Given an explicit source pattern such as:

src/**/*.{cppm,cpp,cc,c}

mcpp run should not recursively enumerate unrelated directories such as:

compat/bun
compat/node
target
.mcpp

The command should reuse the same source-discovery and dependency-resolution cache as mcpp build, then launch the already-built binary.

Possible implementation direction

  1. Derive the fixed directory prefix from a source glob and walk only that prefix. For src/**/*, do not start traversal at ..
  2. Treat Git submodule boundaries as excluded from package source discovery unless explicitly declared as a package/member.
  3. Skip generated/cache directories such as target and .mcpp during source discovery.
  4. Cache source discovery and resolved dependency metadata so mcpp run does not repeat the full scan after mcpp build.
  5. Add a regression test containing a large unrelated directory or submodule and assert that mcpp run remains close to the cached mcpp build time.

Impact

This makes the normal development command slow for every invocation and becomes worse as compatibility corpora grow. The runtime itself is fast; the delay is entirely in the mcpp run/resolve path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions