diff --git a/llvm/utils/lit/lit/ProgressBar.py b/llvm/utils/lit/lit/ProgressBar.py --- a/llvm/utils/lit/lit/ProgressBar.py +++ b/llvm/utils/lit/lit/ProgressBar.py @@ -253,7 +253,7 @@ elapsed = time.time() - self.startTime if percent > .0001 and elapsed > 1: total = elapsed / percent - eta = int(total - elapsed) + eta = total - elapsed h = eta//3600. m = (eta//60) % 60 s = eta % 60 diff --git a/llvm/utils/lit/lit/display.py b/llvm/utils/lit/lit/display.py --- a/llvm/utils/lit/lit/display.py +++ b/llvm/utils/lit/lit/display.py @@ -5,8 +5,10 @@ if opts.quiet: return NopDisplay() - of_total = (' of %d' % total_tests) if (tests != total_tests) else '' - header = '-- Testing: %d%s tests, %d workers --' % (tests, of_total, workers) + num_tests = len(tests) + of_total = (' of %d' % total_tests) if (num_tests != total_tests) else '' + header = '-- Testing: %d%s tests, %d workers --' % ( + num_tests, of_total, workers) progress_bar = None if opts.succinct and opts.useProgressBar: @@ -21,6 +23,42 @@ return Display(opts, tests, header, progress_bar) +class ProgressPredictor(object): + def __init__(self, tests): + self.completed = 0 + self.time_elapsed = 0.0 + self.predictable_tests_remaining = 0 + self.predictable_time_remaining = 0.0 + self.unpredictable_tests_remaining = 0 + + for test in tests: + if test.previous_elapsed: + self.predictable_tests_remaining += 1 + self.predictable_time_remaining += test.previous_elapsed + else: + self.unpredictable_tests_remaining += 1 + + def update(self, test): + self.completed += 1 + self.time_elapsed += test.result.elapsed + + if test.previous_elapsed: + self.predictable_tests_remaining -= 1 + self.predictable_time_remaining -= test.previous_elapsed + else: + self.unpredictable_tests_remaining -= 1 + + # NOTE: median would be more precise, but might be too slow. + average_test_time = (self.time_elapsed + self.predictable_time_remaining) / \ + (self.completed + self.predictable_tests_remaining) + unpredictable_time_remaining = average_test_time * \ + self.unpredictable_tests_remaining + total_time_remaining = self.predictable_time_remaining + unpredictable_time_remaining + total_time = self.time_elapsed + total_time_remaining + + return self.time_elapsed / total_time + + class NopDisplay(object): def print_header(self): pass def update(self, test): pass @@ -30,8 +68,10 @@ class Display(object): def __init__(self, opts, tests, header, progress_bar): self.opts = opts - self.tests = tests + self.num_tests = len(tests) self.header = header + self.progress_predictor = ProgressPredictor( + tests) if progress_bar else None self.progress_bar = progress_bar self.completed = 0 @@ -55,7 +95,7 @@ if self.progress_bar: if test.isFailure(): self.progress_bar.barColor = 'RED' - percent = float(self.completed) / self.tests + percent = self.progress_predictor.update(test) self.progress_bar.update(percent, test.getFullName()) def clear(self, interrupted): @@ -66,7 +106,7 @@ # Show the test result line. test_name = test.getFullName() print('%s: %s (%d of %d)' % (test.result.code.name, test_name, - self.completed, self.tests)) + self.completed, self.num_tests)) # Show the test failure output, if requested. if (test.isFailure() and self.opts.showOutput) or \ diff --git a/llvm/utils/lit/lit/main.py b/llvm/utils/lit/lit/main.py --- a/llvm/utils/lit/lit/main.py +++ b/llvm/utils/lit/lit/main.py @@ -205,8 +205,7 @@ def run_tests(tests, lit_config, opts, discovered_tests): workers = min(len(tests), opts.workers) - display = lit.display.create_display(opts, len(tests), discovered_tests, - workers) + display = lit.display.create_display(opts, tests, discovered_tests, workers) run = lit.run.Run(tests, lit_config, workers, display.update, opts.max_failures, opts.timeout)