Path: blob/master/benchmark/benchmark_snapshot.py
1089 views
import argparse1import math2from concurrent.futures import ThreadPoolExecutor3from functools import partial4from statistics import mean5from timeit import default_timer67import psutil8import requests9from PIL import Image10from psutil import cpu_percent, process_iter1112from plate_recognition import recognition_api131415def parse_arguments():16parser = argparse.ArgumentParser(description="Benchmark SDK.")17parser.add_argument(18"--sdk-url",19help="Url to self hosted sdk For example, http://localhost:8080",20default="http://localhost:8080",21)22parser.add_argument(23"--threads", help="Use thread to parallelize API calls", default=4, type=int24)25parser.add_argument("--image", default="assets/car-4k.jpg")26parser.add_argument("--mmc", action="store_true")27parser.add_argument("--iterations", default=50, type=int)28parser.add_argument("--blur", action="store_true")29return parser.parse_args()303132def print_table(results):33if not results:34return35print("| Mode | Resolution | Speed | l_min | l_max |")36print("| -------- | ---------- | ------- | ------ | ------ |")37for result in results:38print(39"| {mode:8s} | {resolution:10s} | {avg:7.1f} | {min:6.1f} | {max:6.1f} |".format(40**result41)42)434445def blur_api(url, fp):46"""47Upload an Image to url for burring48"""49response = requests.post(url, files={"upload": fp})50if response.status_code < 200 or response.status_code > 300:51if response.status_code == 400:52msg = response.json().get("error")53else:54msg = response.text55raise Exception(f"Error performing blur: {msg}")5657blur_data = response.json().get("blur")58if blur_data is None:59raise Exception(60"Error - ensure blurring on server is enabled - "61"https://guides.platerecognizer.com/docs/blur/api-reference#post-parameters"62)63return blur_data646566def call_duration(path, sdk_url, config, mmc, blur):67now = default_timer()68with open(path, "rb") as fp:69if blur:70blur_api(sdk_url, fp)71else:72recognition_api(73fp, sdk_url=sdk_url, config=config, mmc="true" if mmc else "false"74)75return (default_timer() - now) * 1000767778def benchmark(args, executor):79image = Image.open(args.image)80for resolution in [81(800, 600),82(1280, 720),83(1920, 1080),84(2560, 1440),85(3840, 2160),86]:87image.resize(resolution).save("/tmp/platerec-benchmark.jpg")88configs = [{}] if args.blur else [{}, dict(mode="fast")]8990for config in configs:91stats = list(92executor.map(93partial(94call_duration,95sdk_url=args.sdk_url,96config=config,97mmc=args.mmc,98blur=args.blur,99),100["/tmp/platerec-benchmark.jpg"] * args.iterations,101)102)103yield dict(104resolution=f"{resolution[0]}x{resolution[1]}",105mode=config.get("mode", "regular"),106min=min(stats),107max=max(stats),108avg=mean(stats),109)110111112def mem_usage():113usage = {}114for process in process_iter():115try:116if "main.py" in process.cmdline() or "start.sh" in process.cmdline():117usage[process.pid] = process.memory_info()118except psutil.ZombieProcess:119pass120return usage121122123def convert_size(size_bytes):124if size_bytes == 0:125return "0B"126sign = ""127if size_bytes < 0:128size_bytes *= -1129sign = "-"130size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")131i = int(math.floor(math.log(size_bytes, 1024)))132p = math.pow(1024, i)133s = round(size_bytes / p, 2)134return f"{sign}{s} {size_name[i]}"135136137def main():138args = parse_arguments()139initial_mem = mem_usage()140cpu_percent() # first time this is called it will return a meaningless 0.0141with ThreadPoolExecutor(max_workers=args.threads) as executor:142# Warmup143list(144executor.map(145partial(146call_duration,147sdk_url=args.sdk_url,148config={},149mmc=args.mmc,150blur=args.blur,151),152[args.image] * 2,153)154)155# Benchmark156results = list(benchmark(args, executor))157158# Memory Usage159print(f"CPU: {cpu_percent()}%")160for pid, mem in mem_usage().items():161print(162f"PID: {pid:5}, "163f"RES {convert_size(mem.rss):10} ({convert_size(mem.rss - initial_mem[pid].rss):10}), "164f"SHR {convert_size(mem.shared):10} ({convert_size(mem.shared - initial_mem[pid].shared):10})"165)166print_table(results)167168169if __name__ == "__main__":170main()171172173