Skip to content

Commit 031c8b9

Browse files
committed
[Benchmarks] Archive old data
Archive old benchmark data so it is not loaded in the dashboard. The default value for archiving is: - for Baseline_* runs for data older than 90 days, - for all other runs for data older than 14 days. Add a UI option for loading archived data.
1 parent 8b445d6 commit 031c8b9

File tree

6 files changed

+240
-31
lines changed

6 files changed

+240
-31
lines changed

devops/scripts/benchmarks/history.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import socket
1010
from utils.result import Result, BenchmarkRun
1111
from options import Compare, options
12-
from datetime import datetime, timezone
12+
from datetime import datetime, timezone, timedelta
1313
from utils.utils import run
1414
from utils.validate import Validate
1515

@@ -223,3 +223,23 @@ def get_compare(self, name: str) -> BenchmarkRun:
223223
return self.compute_average(data)
224224

225225
raise Exception("invalid compare type")
226+
227+
def partition_runs_by_age(self) -> tuple[list[BenchmarkRun], list[BenchmarkRun]]:
228+
"""
229+
Partition runs into current and archived based on their age.
230+
Returns:
231+
tuple: (current_runs, archived_runs)
232+
"""
233+
current_runs = []
234+
archived_runs = []
235+
236+
for run in self.runs:
237+
archive_after = options.archive_baseline_days if run.name.startswith("Baseline_") else options.archive_pr_days
238+
cutoff_date = datetime.now(timezone.utc) - timedelta(days=archive_after)
239+
240+
if run.date > cutoff_date:
241+
current_runs.append(run)
242+
else:
243+
archived_runs.append(run)
244+
245+
return current_runs, archived_runs

devops/scripts/benchmarks/html/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ <h3>Display Options</h3>
5353
<input type="checkbox" id="custom-range">
5454
Adjust Y-axis for comparisons
5555
</label>
56+
<label title="Load older benchmark results that have been archived.">
57+
<input type="checkbox" id="show-archived-data">
58+
Include archived runs
59+
</label>
5660
</div>
5761
</div>
5862

devops/scripts/benchmarks/html/scripts.js

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
let activeRuns = new Set(defaultCompareNames);
88
let chartInstances = new Map();
99
let suiteNames = new Set();
10-
let timeseriesData, barChartsData, allRunNames;
1110
let activeTags = new Set();
11+
let timeseriesData, barChartsData, allRunNames;
1212
let layerComparisonsData;
1313
let latestRunsLookup = new Map();
1414
let pendingCharts = new Map(); // Store chart data for lazy loading
1515
let chartObserver; // Intersection observer for lazy loading charts
1616
let annotationsOptions = new Map(); // Global options map for annotations
17+
let archivedDataLoaded = false;
1718

1819
// DOM Elements
1920
let runSelect, selectedRunsDiv, suiteFiltersContainer, tagFiltersContainer;
@@ -577,6 +578,12 @@ function updateURL() {
577578
} else {
578579
url.searchParams.set('customRange', 'true');
579580
}
581+
582+
if (!isArchivedDataEnabled()) {
583+
url.searchParams.delete('archived');
584+
} else {
585+
url.searchParams.set('archived', 'true');
586+
}
580587

581588
history.replaceState(null, '', url);
582589
}
@@ -835,6 +842,9 @@ function setupRunSelector() {
835842
runSelect = document.getElementById('run-select');
836843
selectedRunsDiv = document.getElementById('selected-runs');
837844

845+
// Clear existing options first to prevent duplicates when reloading with archived data
846+
runSelect.innerHTML = '';
847+
838848
allRunNames.forEach(name => {
839849
const option = document.createElement('option');
840850
option.value = name;
@@ -848,6 +858,9 @@ function setupRunSelector() {
848858
function setupSuiteFilters() {
849859
suiteFiltersContainer = document.getElementById('suite-filters');
850860

861+
// Clear existing suite filters before adding new ones
862+
suiteFiltersContainer.innerHTML = '';
863+
851864
benchmarkRuns.forEach(run => {
852865
run.results.forEach(result => {
853866
suiteNames.add(result.suite);
@@ -883,10 +896,16 @@ function isCustomRangesEnabled() {
883896
return rangesToggle.checked;
884897
}
885898

899+
function isArchivedDataEnabled() {
900+
const archivedDataToggle = document.getElementById('show-archived-data');
901+
return archivedDataToggle.checked;
902+
}
903+
886904
function setupToggles() {
887905
const notesToggle = document.getElementById('show-notes');
888906
const unstableToggle = document.getElementById('show-unstable');
889907
const customRangeToggle = document.getElementById('custom-range');
908+
const archivedDataToggle = document.getElementById('show-archived-data');
890909

891910
notesToggle.addEventListener('change', function () {
892911
// Update all note elements visibility
@@ -908,10 +927,26 @@ function setupToggles() {
908927
// redraw all charts
909928
updateCharts();
910929
});
930+
931+
// Add event listener for archived data toggle
932+
if (archivedDataToggle) {
933+
archivedDataToggle.addEventListener('change', function() {
934+
if (archivedDataToggle.checked) {
935+
loadArchivedData();
936+
} else {
937+
if (archivedDataLoaded) {
938+
// Reload the page to reset
939+
location.reload();
940+
}
941+
}
942+
updateURL();
943+
});
944+
}
911945

912946
// Initialize from URL params if present
913947
const notesParam = getQueryParam('notes');
914948
const unstableParam = getQueryParam('unstable');
949+
const archivedParam = getQueryParam('archived');
915950

916951
if (notesParam !== null) {
917952
let showNotes = notesParam === 'true';
@@ -927,11 +962,22 @@ function setupToggles() {
927962
if (customRangesParam !== null) {
928963
customRangeToggle.checked = customRangesParam === 'true';
929964
}
965+
966+
if (archivedDataToggle && archivedParam !== null) {
967+
archivedDataToggle.checked = archivedParam === 'true';
968+
969+
if (archivedDataToggle.checked) {
970+
loadArchivedData();
971+
}
972+
}
930973
}
931974

932975
function setupTagFilters() {
933976
tagFiltersContainer = document.getElementById('tag-filters');
934977

978+
// Clear existing tag filters before adding new ones
979+
tagFiltersContainer.innerHTML = '';
980+
935981
const allTags = [];
936982

937983
if (benchmarkTags) {
@@ -1119,6 +1165,94 @@ function loadData() {
11191165
}
11201166
}
11211167

1168+
// Function to load archived data and merge with current data
1169+
// Archived data consists of older benchmark results that have been separated from
1170+
// the primary dataset but are still available for historical analysis.
1171+
function loadArchivedData() {
1172+
const loadingIndicator = document.getElementById('loading-indicator');
1173+
loadingIndicator.style.display = 'block';
1174+
1175+
if (archivedDataLoaded) {
1176+
updateCharts();
1177+
loadingIndicator.style.display = 'none';
1178+
return;
1179+
}
1180+
1181+
if (typeof remoteDataUrl !== 'undefined' && remoteDataUrl !== '') {
1182+
// For remote data, construct the archive URL by adding _archive before the extension
1183+
const archiveUrl = remoteDataUrl.replace(/(\.[^.]+)$/, '_archive$1');
1184+
1185+
fetch(archiveUrl)
1186+
.then(response => {
1187+
if (!response.ok) { throw new Error(`Got response status ${response.status}.`) }
1188+
return response.json();
1189+
})
1190+
.then(data => {
1191+
const archivedRuns = data.runs || data;
1192+
1193+
// Merge the archived runs with current runs
1194+
benchmarkRuns = benchmarkRuns.concat(archivedRuns);
1195+
1196+
// Merge metadata and tags if available
1197+
if (data.metadata) {
1198+
benchmarkMetadata = { ...benchmarkMetadata, ...data.metadata };
1199+
}
1200+
1201+
if (data.tags) {
1202+
benchmarkTags = { ...benchmarkTags, ...data.tags };
1203+
}
1204+
1205+
archivedDataLoaded = true;
1206+
initializeCharts();
1207+
})
1208+
.catch(error => {
1209+
console.error('Error fetching archived data:', error);
1210+
})
1211+
.finally(() => {
1212+
loadingIndicator.style.display = 'none';
1213+
});
1214+
} else {
1215+
// For local data, try to load data_archive.js
1216+
const script = document.createElement('script');
1217+
script.src = 'data_archive.js';
1218+
script.onload = () => {
1219+
if (typeof archivedBenchmarkRuns !== 'undefined') {
1220+
// Merge the archived runs with current runs
1221+
benchmarkRuns = benchmarkRuns.concat(archivedBenchmarkRuns);
1222+
1223+
// Merge metadata and tags if available
1224+
if (typeof archivedBenchmarkMetadata !== 'undefined') {
1225+
benchmarkMetadata = { ...benchmarkMetadata, ...archivedBenchmarkMetadata };
1226+
}
1227+
1228+
if (typeof archivedBenchmarkTags !== 'undefined') {
1229+
benchmarkTags = { ...benchmarkTags, ...archivedBenchmarkTags };
1230+
}
1231+
1232+
archivedDataLoaded = true;
1233+
1234+
archivedBenchmarkRuns.forEach(runName => {
1235+
if (!activeRuns.has(runName)) {
1236+
activeRuns.add(runName);
1237+
}
1238+
});
1239+
1240+
initializeCharts();
1241+
} else {
1242+
console.error('Archived runs data not found in data_archive.js');
1243+
}
1244+
loadingIndicator.style.display = 'none';
1245+
};
1246+
1247+
script.onerror = () => {
1248+
console.error('Failed to load data_archive.js');
1249+
loadingIndicator.style.display = 'none';
1250+
};
1251+
1252+
document.head.appendChild(script);
1253+
}
1254+
}
1255+
11221256
// Initialize when DOM is ready
11231257
document.addEventListener('DOMContentLoaded', () => {
11241258
loadData();

devops/scripts/benchmarks/main.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def main(directory, additional_env_vars, save_name, compare_names, filter):
316316
if options.output_directory is None:
317317
html_path = os.path.join(os.path.dirname(__file__), "html")
318318

319-
generate_html(history.runs, compare_names, html_path, metadata)
319+
generate_html(history, compare_names, html_path, metadata)
320320

321321

322322
def validate_and_parse_env_args(env_args):
@@ -558,6 +558,22 @@ def validate_and_parse_env_args(env_args):
558558
help="Location of detect_version.cpp used to query e.g. DPC++, L0",
559559
default=None,
560560
)
561+
parser.add_argument(
562+
"--archive-baseline-after",
563+
type=int,
564+
help="Archive baseline results (runs starting with 'Baseline_') older than this many days. "
565+
"Archived results are stored separately and can be viewed in the HTML UI by enabling "
566+
"'Include archived runs'. This helps manage the size of the primary dataset.",
567+
default=options.archive_baseline_days,
568+
)
569+
parser.add_argument(
570+
"--archive-pr-after",
571+
type=int,
572+
help="Archive PR and other non-baseline results older than this many days. "
573+
"Archived results are stored separately and can be viewed in the HTML UI by enabling "
574+
"'Include archived runs'. PR runs typically have a shorter retention period than baselines.",
575+
default=options.archive_pr_days,
576+
)
561577

562578
args = parser.parse_args()
563579
additional_env_vars = validate_and_parse_env_args(args.env)

devops/scripts/benchmarks/options.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from enum import Enum
33
import multiprocessing
44

5-
from presets import presets
6-
75

86
class Compare(Enum):
97
LATEST = "latest"
@@ -88,6 +86,12 @@ class Options:
8886
# CI scripts vs SYCl build source.
8987
github_repo_override: str = None
9088
git_commit_override: str = None
89+
# Archiving settings
90+
# Archived runs are stored separately from the main dataset but are still accessible
91+
# via the HTML UI when "Include archived runs" is enabled
92+
archive_baseline_days: int = 90 # Archive Baseline_* runs after 90 days
93+
archive_pr_days: int = 14 # Archive other (PR/dev) runs after 14 days
94+
9195

9296
detect_versions: DetectVersionsOptions = field(
9397
default_factory=DetectVersionsOptions

0 commit comments

Comments
 (0)