Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

133 lines
5.8 KiB
Python
Executable File

#!/usr/bin/env python3
# ===----------------------------------------------------------------------===##
#
# 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, Optional, Set
import argparse
import json
import logging
import os
import pathlib
import subprocess
import sys
import time
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_sort_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 print them to standard output.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
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('--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('--machine', type=str, required=True,
help='The name of the machine that we are producing results for on the LNT instance.')
parser.add_argument('-d', '--delay', type=int, required=False, default=60,
help='The delay (in seconds) to wait before successive polls.')
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('-v', '--verbose', action='count', default=0,
help='Verbosity level: passing the option multiple times increases the level.')
args = parser.parse_args(argv)
VERY_VERBOSE = logging.DEBUG - 1
if args.verbose == 1:
logging.basicConfig(level=logging.INFO)
elif args.verbose == 2:
logging.basicConfig(level=logging.DEBUG)
elif args.verbose > 2:
logging.basicConfig(level=VERY_VERBOSE)
last_commit: Optional[str] = None # last commit printed
while True:
logging.info(f'Fetching all libc++ commits in {args.git_repo}')
all_commits = get_all_libcxx_commits(args.git_repo)
logging.log(VERY_VERBOSE, f'Found all libc++ commits: {all_commits}')
logging.info(f'Getting benchmarked commits for {args.machine} from {args.lnt_url}')
benchmarked_commits = get_benchmarked_commits(args.lnt_url, args.test_suite, args.machine)
logging.log(VERY_VERBOSE, f'Found benchmarked commits: {benchmarked_commits}')
# Print the next commit that should be benchmarked, but only when it changes over the one
# that we just printed. This ensures that we don't repeatedly print that the same benchmark
# should be benchmarked, which would otherwise happen when we are running the benchmarks but
# have not submitted to LNT yet.
commits_to_benchmark = all_commits - benchmarked_commits
if not commits_to_benchmark:
logging.info('No more commits to benchmark')
else:
commits_to_benchmark = git_sort_revlist(args.git_repo, list(commits_to_benchmark))
most_recent = commits_to_benchmark[-1]
if most_recent != last_commit:
logging.info(f'Selected {most_recent}')
print(most_recent, flush=True)
last_commit = most_recent
logging.debug(f'Waiting {args.delay}s before next poll')
time.sleep(args.delay)
if __name__ == '__main__':
main(sys.argv[1:])