#!/usr/bin/env python3 import argparse from concurrent.futures import ThreadPoolExecutor import time parser = argparse.ArgumentParser() parser.add_argument('--size', '-s', type=int, default=8192, help='bytes in each chunk') parser.add_argument('--chunks', '-n', type=int, default=8192, help='number of chunks to join') parser.add_argument('--threads', '-t', type=int, default=1, help='number of threads') parser.add_argument('--repeats', '-r', type=int, help='number of times to join') args = parser.parse_args() if args.repeats is None: args.repeats = max(3, 10**9 // (args.size * args.chunks)) def one_thread(args): chunks = [b'x' * args.size for _ in range(args.chunks)] start = time.monotonic() for repeat in range(args.repeats): b''.join(chunks) elapsed = time.monotonic() - start return elapsed pool = ThreadPoolExecutor(args.threads) futures = [pool.submit(one_thread, args) for _ in range(args.threads)] elapsed = 0.0 for future in futures: elapsed += future.result() avg_elapsed = elapsed / args.threads rate = args.size * args.chunks * args.repeats / avg_elapsed rate_mb = rate / 1e6 print(f'{args.size},{args.chunks},{args.threads},{rate_mb:.2f}')