[libcxx-commits] [libcxx] [libc++] Add scripts to run benchmarks and submit to LNT on a regular basis (PR #180849)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Feb 11 03:36:15 PST 2026
================
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+# ===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ===----------------------------------------------------------------------===##
+
+from typing import List, Set
+import argparse
+import json
+import logging
+import os
+import pathlib
+import subprocess
+import sys
+
+
+def directory_path(string):
+ if os.path.isdir(string):
+ return pathlib.Path(string)
+ else:
+ raise NotADirectoryError(string)
+
+def api(lnt_url: str, test_suite: str, endpoint: str):
+ url = f'{lnt_url}/api/db_default/v4/{test_suite}{endpoint}'
+ logging.debug(f'Querying {url}')
+ result = json.loads(subprocess.check_output(['curl', '-sS', url]).decode())
+ return result
+
+def get_benchmarked_commits(lnt_url: str, test_suite: str, machine: str) -> Set[str]:
+ """
+ Return the set of commits that have already been benchmarked on the given LNT
+ instance, test suite and machine.
+ """
+ result = api(lnt_url, test_suite, f'/machines/{machine}')
+ commits = set()
+ if 'runs' not in result: # there is no such machine
+ return set()
+ for run in result['runs']:
+ if 'git_sha' not in run:
+ raise ValueError(f'Found run without a git_sha field: are you using the right LNT test suite? {run}')
+ commits.add(run['git_sha'])
+ return commits
+
+def git_rev_list(git_repo: str, paths: List[str] = []) -> List[str]:
+ """
+ Return the list of all revisions in the given Git repository. Older commits are earlier in the list.
+ """
+ cli = ['git', '-C', git_repo, 'rev-list', 'origin', '--', *paths]
+ rev_list = subprocess.check_output(cli).decode().strip().splitlines()
+ return list(reversed(rev_list))
+
+def git_sorted_revlist(git_repo: str, commits: List[str]) -> List[str]:
+ """
+ Return the list of commits sorted by their chronological order (from oldest to newest) in the
+ provided Git repository. Items earlier in the list are older than items later in the list.
+ """
+ revlist_cmd = ['git', '-C', git_repo, 'rev-list', '--no-walk'] + list(commits)
+ revlist = subprocess.check_output(revlist_cmd, text=True).strip().splitlines()
+ return list(reversed(revlist))
+
+def get_all_libcxx_commits(git_repo: str) -> Set[str]:
+ """
+ Return the set of commits available to benchmark for libc++: this is the list of
+ commits that touch code in libc++ that we care to benchmark.
+ """
+ logging.debug(f'Fetching {git_repo}')
+ subprocess.check_call(['git', '-C', git_repo, 'fetch', '--quiet', 'origin'])
+ return set(git_rev_list(git_repo, paths=['libcxx/include', 'libcxx/src']))
+
+
+def main(argv):
+ parser = argparse.ArgumentParser(
+ prog='commit-watch',
+ description='Watch for libc++ commits to run benchmarks on, and run the specified command on them.')
+ parser.add_argument('--machine', type=str, required=True,
+ help='The name of the machine that we are producing results for on the LNT instance.')
+ parser.add_argument('--test-suite', type=str, required=True,
+ help='The name of the test suite that we are producing results for on the LNT instance.')
+ parser.add_argument('--lnt-url', type=str, required=True,
+ help='The URL of the LNT instance to use as the source of truth for finding already-benchmarked commits.')
+ parser.add_argument('--git-repo', type=directory_path, default=os.getcwd(),
+ help='Optional path to the Git repository to use. By default, the current working directory is used.')
+ parser.add_argument('callback', nargs=argparse.REMAINDER,
+ help='The command to run on each commit that we determine to require benchmarking. Should be provided last and '
+ 'separated from other arguments with a `--`.')
+ args = parser.parse_args(argv)
+
+ logging.basicConfig(level=logging.INFO)
+
+ # Gather callback command
+ if not args.callback:
+ raise ValueError('A callback must be provided')
+ else:
+ if args.callback[0] != '--':
+ raise ValueError('For clarity, the callback must be separated from other options by --')
+ callback = args.callback[1:]
----------------
philnik777 wrote:
```suggestion
elif args.callback[0] != '--':
raise ValueError('For clarity, the callback must be separated from other options by --')
callback = args.callback[1:]
```
I think that makes is clearer what's going on?
https://github.com/llvm/llvm-project/pull/180849
More information about the libcxx-commits
mailing list