Path: blob/master/benchmark/benchmark_snapshot.py
641 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 [(800, 600), (1280, 720), (1920, 1080), (2560, 1440)]:81image.resize(resolution).save("/tmp/platerec-benchmark.jpg")82if args.blur:83configs = [{}]84else:85configs = [{}, dict(mode="fast")]8687for config in configs:88now = default_timer()89stats = list(90executor.map(91partial(92call_duration,93sdk_url=args.sdk_url,94config=config,95mmc=args.mmc,96blur=args.blur,97),98["/tmp/platerec-benchmark.jpg"] * args.iterations,99)100)101duration = (default_timer() - now) * 1000102yield dict(103resolution="%sx%s" % resolution,104mode=config.get("mode", "regular"),105min=min(stats),106max=max(stats),107avg=mean(stats),108)109110111def mem_usage():112usage = {}113for process in process_iter():114try:115if "main.py" in process.cmdline() or "start.sh" in process.cmdline():116usage[process.pid] = process.memory_info()117except psutil.ZombieProcess:118pass119return usage120121122def convert_size(size_bytes):123if size_bytes == 0:124return "0B"125sign = ""126if size_bytes < 0:127size_bytes *= -1128sign = "-"129size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")130i = int(math.floor(math.log(size_bytes, 1024)))131p = math.pow(1024, i)132s = round(size_bytes / p, 2)133return f"{sign}{s} {size_name[i]}"134135136def main():137args = parse_arguments()138initial_mem = mem_usage()139cpu_percent() # first time this is called it will return a meaningless 0.0140with ThreadPoolExecutor(max_workers=args.threads) as executor:141# Warmup142list(143executor.map(144partial(145call_duration,146sdk_url=args.sdk_url,147config={},148mmc=args.mmc,149blur=args.blur,150),151[args.image] * 2,152)153)154# Benchmark155results = list(benchmark(args, executor))156157# Memory Usage158print(f"CPU: {cpu_percent()}%")159for pid, mem in mem_usage().items():160print(161f"PID: {pid:5}, "162f"RES {convert_size(mem.rss):10} ({convert_size(mem.rss - initial_mem[pid].rss):10}), "163f"SHR {convert_size(mem.shared):10} ({convert_size(mem.shared - initial_mem[pid].shared):10})"164)165print_table(results)166167168if __name__ == "__main__":169main()170171172