From 93e17e14b8a732d398a27ec005dd0289f74170a0 Mon Sep 17 00:00:00 2001 From: xenofem Date: Tue, 23 Nov 2021 01:39:11 -0500 Subject: [PATCH] refactor around deltas, add configurable decay coefficient and smarter halting --- impatient | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/impatient b/impatient index cad3eb1..8e18462 100755 --- a/impatient +++ b/impatient @@ -12,11 +12,21 @@ parser = argparse.ArgumentParser(description='Display progress and time estimate parser.add_argument('-f', '--final', type=str, help='Expected final size/value at completion, optionally with a K/M/G/T suffix') parser.add_argument('-i', '--interval', type=int, default=10, help='Interval in seconds between samples (default 10)') parser.add_argument('-w', '--window', type=int, default=100, help='Number of samples to keep for the sliding window (default 100)') +parser.add_argument('-d', '--decay', type=float, default=1, help='Decay coefficient for older samples (default 1). Must be between 0 and 1 inclusive. The lower this is, the more responsive/swingy the estimate will be.') tracker_types = parser.add_mutually_exclusive_group(required=True) tracker_types.add_argument('-p', '--path', type=str, help='Track total disk usage of a given path') tracker_types.add_argument('-c', '--command', type=str, help='Track value returned by a shell command; this should return a single number, optionally with a K/M/G/T suffix') args = parser.parse_args() +if args.interval < 1: + print('interval must be at least 1', file=sys.stderr) + exit(1) +if args.window < 1: + print('window size must be at least 1', file=sys.stderr) + exit(1) +if args.decay < 0 or args.decay > 1: + print('decay coefficient must be between 0 and 1', file=sys.stderr) + exit(1) def parse_value(v): suffix = v[-1].upper() @@ -57,19 +67,26 @@ if args.final: else: final = None -samples = [current_val()] +deltas = [] +current = current_val() while True: time.sleep(args.interval) - current = current_val() + new = current_val() - samples.append(current) - if len(samples) < 2: - continue - if len(samples) > args.window: - samples = samples[-args.window:] + deltas.append(new - current) + current = new + if len(deltas) > args.window: + deltas = deltas[-args.window:] - rate = (current - samples[0])/((len(samples)-1)*args.interval) + total = 0 + divisor = 0 + coeff = 1 + for d in deltas[::-1]: + total += coeff*d + divisor += coeff + coeff *= args.decay + rate = total/(divisor*args.interval) print('\033[2K\r', end='') print('{} - {}/s'.format(display_value(current), display_value(rate)), end='') @@ -86,6 +103,6 @@ while True: ), end='') sys.stdout.flush() - if final and current >= final: + if final and current >= final and all(d == 0 for d in deltas[-10:]): print() break