8.6 KiB
Manifest Runtime Data Format Documentation
This document describes the JSON file formats created by fetch-manifest-data.js.
Overview
The script generates two types of JSON files:
- Detailed data:
manifests.json- Contains all individual manifest runs with task IDs and commit hashes - Runtimes data:
manifests-runtimes.json- Smaller file grouping runtimes by manifest and job
Both formats use string tables and index-based lookups to minimize file size.
Detailed Data Format (manifests.json)
Top-Level Structure
{
"metadata": { ... },
"manifests": [ ... ],
"jobNames": [ ... ],
"commits": [ ... ],
"prefixes": [ ... ],
"tasks": { ... },
"runs": { ... }
}
metadata
Contains information about the data collection:
{
"date": "2025-02-04",
"repository": "mozilla-central",
"generatedAt": "2025-02-05T14:24:33.451Z",
"processedJobCount": 1234,
"failedJobCount": 56,
"skippedJobCount": 789,
"manifestCount": 3456,
"jobNameCount": 45,
"timingCount": 12345
}
String Tables
All strings are deduplicated and stored once:
{
"manifests": [
"dom/tests/mochitest/general/mochitest.toml",
"toolkit/components/extensions/test/mochitest/mochitest.toml",
...
],
"jobNames": [
"test-linux2404-64/debug-mochitest-browser-chrome",
"test-macosx1470-64/opt-mochitest-plain",
...
],
"commits": [
"f37a6863f87aeeb870b16223045ea7614b1ba0a7",
"abc123def456789012345678901234567890abcd",
...
],
"prefixes": [
"mochitest-browser-chrome",
"mochitest-plain",
"wpt",
"xpcshell",
"reftest",
...
]
}
tasks
Object containing parallel arrays with task metadata:
{
"tasks": {
"id": [
"YJJe4a0CRIqbAmcCo8n63w",
"XPPf5b1DRJrcBndDp9o74x.1",
...
],
"jobName": [5, 12, 8, 15, ...],
"commitId": [0, 0, 1, 1, ...],
"prefix": [0, 1, 2, 1, ...]
}
}
All arrays are parallel - index i corresponds to the same task:
id[i]: Task ID string (includes retry suffix when retry > 0, e.g.,taskId.1)jobName[i]: Index intojobNamesarray (full job name including chunk number)commitId[i]: Index intocommitsarrayprefix[i]: Index intoprefixesarray (artifact type used)
Note: The jobNames table contains both base names (without chunks, used in runs.jobNameIds) and full names (with chunks, used in tasks.jobName).
runs
Parallel arrays containing timing data:
{
"runs": {
"manifestIds": [0, 1, 0, 2, ...],
"jobNameIds": [0, 0, 1, 1, ...],
"taskIds": [0, 1, 2, 3, ...],
"durations": [1234, 5678, 2345, ...]
}
}
All arrays are parallel - index i in each array corresponds to the same manifest run:
manifestIds[i]: Index intomanifestsarrayjobNameIds[i]: Index intojobNamesarray (base name without chunk)taskIds[i]: Index intotasks.idarraydurations[i]: Runtime in milliseconds
Example lookup:
const i = 5;
const manifest = data.manifests[data.runs.manifestIds[i]];
const jobBaseName = data.jobNames[data.runs.jobNameIds[i]];
const duration = data.runs.durations[i];
// Get task details
const taskIdx = data.runs.taskIds[i];
const taskId = data.tasks.id[taskIdx];
const fullJobName = data.jobNames[data.tasks.jobName[taskIdx]];
const commitIdx = data.tasks.commitId[taskIdx];
const commit = data.commits[commitIdx];
const prefixIdx = data.tasks.prefix[taskIdx];
const prefix = data.prefixes[prefixIdx];
// Open in Treeherder
const treeherderUrl = `https://treeherder.mozilla.org/#/jobs?repo=${data.metadata.repository}&revision=${commit}&selectedTaskRun=${taskId}`;
Runtimes Data Format (manifests-runtimes.json)
Top-Level Structure
{
"metadata": { ... },
"jobNames": [ ... ],
"manifests": { ... }
}
metadata
{
"date": "2025-02-04",
"repository": "mozilla-central",
"generatedAt": "2025-02-05T14:24:33.451Z",
"manifestCount": 3456,
"jobNameCount": 45
}
jobNames
String table for job names:
{
"jobNames": [
"test-linux2404-64/debug-mochitest-browser-chrome",
"test-macosx1470-64/opt-mochitest-plain",
...
]
}
manifests
Object where keys are manifest names and values are objects containing parallel arrays:
{
"manifests": {
"dom/tests/mochitest/general/mochitest.toml": {
"jobs": [0, 1],
"runtimes": [
[1200, 1234, 1250, 1280, 1300],
[2100, 2150, 2200]
]
},
"toolkit/components/extensions/test/mochitest/mochitest.toml": {
"jobs": [0],
"runtimes": [
[3400, 3500, 3600]
]
},
...
}
}
Each manifest has an object containing parallel arrays:
jobs: Array of indices into thejobNamesarrayruntimes: Array of arrays, whereruntimes[i]is the sorted runtime values in milliseconds for the manifest onjobs[i]
Example lookup:
const manifest = "dom/tests/mochitest/general/mochitest.toml";
const manifestData = data.manifests[manifest];
for (let i = 0; i < manifestData.jobs.length; i++) {
const jobName = data.jobNames[manifestData.jobs[i]];
const runtimes = manifestData.runtimes[i];
const median = runtimes[Math.floor(runtimes.length / 2)];
const mean = runtimes.reduce((a, b) => a + b) / runtimes.length;
console.log(`${jobName}: median=${median}ms, mean=${mean}ms, runs=${runtimes.length}`);
}
Use Cases
Detailed File
Purpose: Deep analysis with full traceability to specific CI runs
Use cases:
- Link to specific Treeherder jobs for investigation
- Track timing changes across commits
- Identify which specific runs were slow
- Debug timing regressions
Example: Find all slow runs for a manifest
const targetManifest = "dom/tests/mochitest/general/mochitest.toml";
const manifestId = data.manifests.indexOf(targetManifest);
const threshold = 5000; // ms
const slowRuns = [];
for (let i = 0; i < data.runs.durations.length; i++) {
if (data.runs.manifestIds[i] === manifestId && data.runs.durations[i] > threshold) {
slowRuns.push({
duration: data.runs.durations[i],
job: data.jobNames[data.runs.jobNameIds[i]],
commit: data.commits[data.runs.commitIds[i]],
taskId: data.taskIds[data.runs.taskIds[i]],
});
}
}
Runtimes File
Purpose: Fast dashboard loading and statistical analysis
Use cases:
- Calculate median/mean runtimes per manifest
- Compare timing distributions across jobs
- Identify consistently slow manifests
- Generate runtime estimates for scheduling
Example: Find slowest manifests by median runtime
const manifestStats = [];
for (const [manifestName, manifestData] of Object.entries(data.manifests)) {
let totalMedian = 0;
for (const runtimes of manifestData.runtimes) {
const median = runtimes[Math.floor(runtimes.length / 2)];
totalMedian += median;
}
manifestStats.push({
manifest: manifestName,
avgMedian: totalMedian / manifestData.runtimes.length,
});
}
manifestStats.sort((a, b) => b.avgMedian - a.avgMedian);
const slowest = manifestStats.slice(0, 10);
Data Characteristics
Job Names
Job names in the jobNames table have chunk numbers removed. For example:
test-linux2404-64/debug-mochitest-browser-chrome-5→test-linux2404-64/debug-mochitest-browser-chrometest-macosx1470-64/opt-web-platform-tests-12→test-macosx1470-64/opt-web-platform-tests
Task IDs
Task IDs in the detailed file format:
- Retry 0:
"taskId"(no suffix) - Retry > 0:
"taskId.N"(includes retry number)
Durations
All duration values are in milliseconds and are integers.
Filtering
The data only includes:
- Jobs from
test-*(actual test jobs, not build jobs) - Jobs with
state === "completed"andresultin["success", "testfailed"] - Test harnesses that produce manifest-level timing data (excludes
cppunittest,marionette,gtest, etc.)
Manifests
Manifest names are the full path to the manifest file, typically ending in:
mochitest.tomlbrowser.tomlchrome.tomlxpcshell.toml
For web-platform-tests, manifest names may be test directory paths.
File Size Comparison
Typical file sizes for one day of mozilla-central data:
- Detailed file: ~8 MB (contains all individual runs)
- Runtimes file: ~3 MB (grouped and sorted)
Notes
- Runtimes in the runtimes file are sorted for efficient percentile calculations
- The detailed file allows reconstruction of the runtimes file
- Both files share the same
jobNamestable for consistency - Commit hashes are full 40-character SHA-1 hashes from mozilla-central
- Task IDs can be used with the TaskCluster API or Treeherder UI