From 7474b96d5ade2c1b569617253225f4bc139da926 Mon Sep 17 00:00:00 2001 From: hx507 <72583014+hx507@users.noreply.github.com> Date: Mon, 20 Jun 2022 11:18:34 -0700 Subject: [PATCH] Parallelize clang-tidy hook Currently clang-tidy hook is running in serial, which can be slow if multiple large files are modified. Clang-tidy is trivially parallelize-able per file, so why don't we take advantage of that? Locally it speeds up a ~8 sec clang-tidy run to ~3 sec, which is bottle-necked on largest file changed -- still much faster. --- hooks/clang_tidy.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/hooks/clang_tidy.py b/hooks/clang_tidy.py index d280269..2aa3bc8 100755 --- a/hooks/clang_tidy.py +++ b/hooks/clang_tidy.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python3 -"""Wrapper script for clang-tidy.""" import re import sys from typing import List +import multiprocessing as mp from hooks.utils import StaticAnalyzerCmd @@ -18,21 +17,20 @@ def __init__(self, args: List[str]): self.parse_args(args) self.edit_in_place = "-fix" in self.args or "--fix-errors" in self.args + def tidy_file(self, filename: List[str]): + self.run_command([filename] + self.args) + # Warnings generated aren't important. + self.stderr = re.sub(rb"[\d,]+ warning \S+\s+", b"", self.stderr) + if len(self.stderr) > 0 and "--fix-errors" in self.args: + self.returncode = 1 + return self.returncode, self.stderr + def run(self): """Run clang-tidy. If --fix-errors is passed in, then return code will be 0, even if there are errors.""" - for filename in self.files: - self.run_command([filename] + self.args) - # Warnings generated aren't important. - self.stderr = re.sub(rb"[\d,]+ warning \S+\s+", b"", self.stderr) - if len(self.stderr) > 0 and "--fix-errors" in self.args: - self.returncode = 1 - self.exit_on_error() - + with mp.Pool(mp.cpu_count()) as p: + results = p.map(self.tidy_file, self.files) + ret_codes, stderrs = zip(*results) -def main(argv: List[str] = sys.argv): - cmd = ClangTidyCmd(argv) - cmd.run() - - -if __name__ == "__main__": - main() + self.returncode = max(ret_codes) + self.stderr = b"\n".join(stderrs) + self.exit_on_error()