Stats

June 23, 2026 ยท View on GitHub

The BuildXL.stats file contains (string, ulong) pairs for various stats that happen throughout the build. It is a simple format that is machine parsable. The data contained within the log may change, but the schema of the file is locked.

Units and Conventions

ConventionDescription
MsSuffix noting that the stat is how long something took in milliseconds
TimeToPrefix indicating the wall clock time from the beginning of the build starting until some event happens.
CountA count of how many times something happened within the build session.

Phase stats

Some stats are logged in a standard way at the end of each engine phase. They are prefixed with the phase name, but the remaining items are consistent.

Statistic NameDescription
DurationMsDuration the phase lasted
ProcessAverageThreadCountAverage total thread count of the bxl.exe process during that phase
ProcessMaximumPrivateMBMaximum private MB of memory held by the bxl.exe process during the phase
MachineAverageCPUTimeAverage CPU time on the machine during the phase. This is not limited to the usage of the bxl.exe process
MachineAverageDiskActiveTime.[DriveLetter]The percent active time for each logical disk during the phase. 0 is an idle disk, 100 is a disk with no idle time during the period

Stats

There are many more stats emitted during a build invocation than just the set described below. Search the source code to see how a statistic is being set if you don't see it listed here.

Statistic NameDescription
TelemetryInitialization.DurationMsTime it took to initialize the connection to telemetry
CacheInitialization.DurationMsTime taken to initialize the cache. Some of this time is overlapped with other operations happening concurrently.
CacheInitialization.OverlappedInitializationMsPortion of cache initialization that happens in the background is overlaps other concurrent work.
CacheInitialization.TimeWaitedMsNon-overlapped time waiting for the cache to initialize. A nonzero amount means the build was waiting on the cache to initialize.
FileCombiner.BeginCountNumber of files in the FileCombiner when it is initialized. The FileCombiner is used by the spec file cache and for some DScript incremental frontend operations.
FileCombiner.InitializationTimeMsTime the FileCombiner spent initializing.
FileCombiner.UnreferencedPercentPercent of files in the FileCombiner that were unreferenced at shutdown time
FileCombiner.FinalSizeInMBFinal size of the FileCombiner in MB.
FileCombiner.CompactingTimeMsTime in milliseconds the FileCombiner spent compacting itself.
FileCombiner.EndCountCount of files the FileCombiner had when it was shut down.
FileCombiner.HitsNumber of files that were satisfied by the FileCombiner.
FileCombiner.MissesNumber of files that were not satisfied by the FileCombiner.
ApplyingFilterToPips.DurationMsTime spent computing which pips matched the pip filter. This does not include the time spent scheduling the pips that match the filter.
ApplyFilterAndScheduleReadyNodes.DurationMsTime spent filtering and scheduling nodes. This time includes ApplyinfFilterToPips.DurationMs.
TimeToFirstPipExecutedMsTime from the beginning of the build until the first external process that is launched. This could also be seen as the time to the first cache miss. If the build has no cache miss, this will be the time until the end of the execute phase.
TotalCacheSizeNeededTotal size, in bytes, of all output files and content put into the cache. This is larger than just the output files of the build because it includes additional metadata needed for cache processing.
OutputFilesChangedNumber of output files that changed from the last build.
OutputFilesUnchangedNumber of output files that did not change from the last build.
SourceFilesUnchangedSource files that did not change from the last build.
SourceFilesChangedSource files that changed from the last build
SourceFilesAbsentSource files that existed in a prior build but are now absent.
OutputFilesProducedOutput files that were produced uniquely in this build. This number will not include output files from cache hits.
OutputFilesCopiedFromCacheOutput files that were replayed from cache.
OutputFilesUpToDateOutput files from cache hits that were already in the correct state on disk
CriticalPath.PipDurationMs*Length of the critical path in milliseconds: the sum of each pip's work duration, excluding all queue time (the remote-worker queue wait is subtracted, and local dispatcher queue time is never included). Compare against CriticalPath.TotalDurationMs to see how much resource contention cost.
CriticalPath.ExeDurationMsTotal external process execution time along the critical path. Cache hits record no time here since they do not launch external processes, so this is 0 for a fully cached build.
CriticalPath.TotalRemoteQueueDurationMsTotal time the pips on the critical path spent queued on a remote worker (distributed builds only). Excluded from CriticalPath.PipDurationMs, included in CriticalPath.TotalDurationMs. Per-step values are also emitted as CriticalPath.<Step>_RemoteQueueDurationMs.
CriticalPath.TotalOrchestratorQueueDurationMsTotal time the pips on the critical path spent waiting in the local dispatcher (orchestrator) queues for machine capacity. Per-dispatcher values are also emitted as CriticalPath.<Dispatcher>_OrchestratorQueueDurationMs.
CriticalPath.ChooseWorkerDurationMsTime the pips on the critical path spent selecting a worker.
CriticalPath.TotalDurationMsThe end-to-end length of this critical path, computed from its components as PipDurationMs (work) + remote queue + orchestrator queue + ChooseWorker. For WallClockCriticalPath.TotalDurationMs this is the number to compare against total build time. For CriticalPath.TotalDurationMs note that the chain is selected by work duration (queue excluded), so it contains the queue time of the work-based chain and is therefore not necessarily the build's full end-to-end time; it instead shows the contention overhead paid along the work-based path.
CriticalPath.<Step>DurationMsPer-PipExecutionStep duration totals along the critical path. Additional fine-grained components are emitted under the same prefix (e.g. BeforeExecution_<op>DurationMs, AfterExecution_<op>DurationMs, TotalGrpcDurationMs, TotalQueueRequestDurationMs, CacheMissAnalysisDurationMs, TotalSuspendedDurationMs, TotalRetryDurationMs, TotalRetryCount, TotalPushOutputsToCacheDurationMs).
GraphCacheReuseCheck.DurationMsTime spent checking if there is a pip graph that can be reused.
TimeToFirstPipTime from build invocation until the first pip starts processing.
TimeToFirstPipSyntheticSimilar to TimeToFirstPip, except it is calculated at the end of graph construction. This means it may be slightly smaller than TimeToFirstPip, but it will always be nonzero even if the execute phase is not run

* BuildXL reports two critical paths, emitting the same full suite of statistics under both prefixes. The only difference is how the chain is selected: CriticalPath.* is the longest chain when each pip is measured by its work duration (excluding the time pips spend queued waiting for resources), while WallClockCriticalPath.* is the longest chain when each pip is measured by its full wall-clock duration (including queue/contention time). The CriticalPath.* chain approximates the theoretical fastest end-to-end build and means the same thing on single-machine and distributed builds; the WallClockCriticalPath.* chain is the one that actually gated the build as it ran. The two chains coincide on an uncontended single-machine build. The keys above are listed once with the CriticalPath. prefix, but each is also emitted with the WallClockCriticalPath. prefix.