<commit_before>"""
benchmark data validation librarys

usage:

    python benchmark.py

add case:
    1. create case_{CASE_NAME}.py
    2. implement one or more funcs which can validate the `DATA` in this module
    3. put validate funcs in a dict named `CASES` in case module
"""
import json
from cProfile import runctx
from glob import glob
from os.path import basename, dirname, splitext

import click

from beeprint import pp
from stable_timeit import stable_timeit as timeit

DATA = {
    "user": {"userid": 5},
    "tags": [1, 2, 5, 9999, 1234567890],
    "style": {
        "width": 400,
        "height": 400,
        "border_width": 5,
        "border_style": "solid",
        "border_color": "red",
        "color": "black"
    },
    # "optional": "string"
}
TEXT = json.dumps(DATA)


def make_data():
    return json.loads(TEXT)


def glob_cases():
    files = glob(dirname(__file__) + '/case_*.py')
    cases = {}
    for filename in files:
        module = splitext(basename(filename))[0]
        name = module[len('case_'):]
        cases[name] = __import__(module).CASES
    return cases


CASES = glob_cases()


@click.group()
def cli():
    pass


@cli.command()
def show():
    """show all cases"""
    pp({name: list(cases) for name, cases in CASES.items()})


@cli.command()
def test():
    """test all cases"""
    for name, subcases in CASES.items():
        for subname, f in subcases.items():
            value = f(make_data())
            try:
                ok = (value['user'] == DATA['user'] and
                      value['tags'] == DATA['tags'] and
                      value['style'] == DATA['style'])
            except:
                ok = False
            if ok:
                print('{}:{} OK'.format(name, subname))
            else:
                print('{}:{}'.format(name, subname).center(60, '-'))
                pp(value)


def warmup():
    data = make_data()
    validates = list(CASES['json'].values()) + list(CASES['validr'].values())
    for i in range(10000):
        for f in validates:
            f(data)


@cli.command()
@click.option('--validr', is_flag=True, help='only benchmark validr')
def benchmark(validr):
    """do benchmark"""
    if validr:
        # warmup()
        cases = {'json': CASES['json'], 'validr': CASES['validr']}
    else:
        cases = CASES
    result = {}
    for name, suncases in cases.items():
        for subname, f in suncases.items():
            params = {"f": f, "data": make_data()}
            t = timeit("f(data)", number=100, repeat=500, globals=params)
            result['{}:{}'.format(name, subname)] = t
    from beeprint import pp
    print('speeds'.center(60, '-'))
    pp({k: round(0.1/v) for k, v in result.items()})
    # print('scores'.center(60, '-'))
    # base = result['json:loads-dumps']
    # pp({k: round(base/v*100) for k, v in result.items()})


@cli.command()
def profile():
    """profile validr"""
    for name, f in CASES['validr'].items():
        print(name.center(60, '-'))
        params = {"f": f, "data": make_data()}
        runctx("for i in range(1000000):f(data)", globals=params, locals=None)


if __name__ == "__main__":
    cli()
<commit_msg>update benchmark<commit_after>"""
benchmark data validation librarys

usage:

    python benchmark.py

add case:
    1. create case_{CASE_NAME}.py
    2. implement one or more funcs which can validate the `DATA` in this module
    3. put validate funcs in a dict named `CASES` in case module
"""
import json
from cProfile import runctx
from glob import glob
from os.path import basename, dirname, splitext

import click

from beeprint import pp
from stable_timeit import stable_timeit as timeit

DATA = {
    "user": {"userid": 5},
    "tags": [1, 2, 5, 9999, 1234567890],
    "style": {
        "width": 400,
        "height": 400,
        "border_width": 5,
        "border_style": "solid",
        "border_color": "red",
        "color": "black"
    },
    # "optional": "string"
}
TEXT = json.dumps(DATA)


def make_data():
    return json.loads(TEXT)


def glob_cases():
    files = glob(dirname(__file__) + '/case_*.py')
    cases = {}
    for filename in files:
        module = splitext(basename(filename))[0]
        name = module[len('case_'):]
        cases[name] = __import__(module).CASES
    return cases


CASES = glob_cases()


@click.group()
def cli():
    pass


@cli.command()
def show():
    """show all cases"""
    pp({name: list(cases) for name, cases in CASES.items()})


@cli.command()
def test():
    """test all cases"""
    for name, subcases in CASES.items():
        for subname, f in subcases.items():
            value = f(make_data())
            try:
                ok = (value['user'] == DATA['user'] and
                      value['tags'] == DATA['tags'] and
                      value['style'] == DATA['style'])
            except:
                ok = False
            if ok:
                print('{}:{} OK'.format(name, subname))
            else:
                print('{}:{}'.format(name, subname).center(60, '-'))
                pp(value)


def print_item(name, subname, value):
    print('{}:{} {}'.format(name.rjust(12), subname.ljust(24), value))


@cli.command()
@click.option('--validr', is_flag=True, help='only benchmark validr')
def benchmark(validr):
    """do benchmark"""
    if validr:
        cases = {'json': CASES['json'], 'validr': CASES['validr']}
    else:
        cases = CASES
    result = {}

    print('timeits'.center(60, '-'))
    for name, suncases in cases.items():
        for subname, f in suncases.items():
            params = {'f': f, 'data': make_data()}
            t = timeit('f(data)', number=100, repeat=500, globals=params)
            result[name, subname] = t
            print_item(name, subname, t)

    print('speeds'.center(60, '-'))
    for (name, subname), v in result.items():
        print_item(name, subname, round(0.1/v))

    print('scores'.center(60, '-'))
    base = result['json', 'loads-dumps']
    for (name, subname), v in result.items():
        print_item(name, subname, round(base/v*100))


@cli.command()
def profile():
    """profile validr"""
    for name, f in CASES['validr'].items():
        print(name.center(60, '-'))
        params = {"f": f, "data": make_data()}
        runctx("for i in range(1000000):f(data)", globals=params, locals=None)


if __name__ == "__main__":
    cli()

{'fraction_non_alphanumeric': 0.16590873451466207, 'fraction_numerical': 0.01897443939156343, 'mean_word_length': 2.498628634119583, 'pattern_counts': {'":': 30, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1512273', 'n_tokens_mistral': 2174, 'n_tokens_neox': 2042, 'n_words': 565}