Blame tests/functional/log_callsite_bench_gen.py

Packit Service f88c7f
#!/usr/bin/python
Packit Service f88c7f
# Copyright 2017 Red Hat, Inc.
Packit Service f88c7f
#
Packit Service f88c7f
# Author: Jan Pokorny <jpokorny@redhat.com>
Packit Service f88c7f
#
Packit Service f88c7f
# This file is part of libqb.
Packit Service f88c7f
#
Packit Service f88c7f
# libqb is free software: you can redistribute it and/or modify
Packit Service f88c7f
# it under the terms of the GNU Lesser General Public License as published by
Packit Service f88c7f
# the Free Software Foundation, either version 2.1 of the License, or
Packit Service f88c7f
# (at your option) any later version.
Packit Service f88c7f
#
Packit Service f88c7f
# libqb is distributed in the hope that it will be useful,
Packit Service f88c7f
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service f88c7f
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service f88c7f
# GNU Lesser General Public License for more details.
Packit Service f88c7f
#
Packit Service f88c7f
# You should have received a copy of the GNU Lesser General Public License
Packit Service f88c7f
# along with libqb.  If not, see <http://www.gnu.org/licenses/>.
Packit Service f88c7f
Packit Service f88c7f
# expected to work with both Python 2.6+/3+
Packit Service f88c7f
from __future__ import print_function
Packit Service f88c7f
Packit Service f88c7f
"""Generate callsite-heavy logging client so as to evaluate use of resources"""
Packit Service f88c7f
Packit Service f88c7f
from getopt import GetoptError, getopt
Packit Service f88c7f
from math import ceil, floor, log10
Packit Service f88c7f
#from pprint import pprint
Packit Service f88c7f
#from random import shuffle
Packit Service f88c7f
from sys import argv, exit
Packit Service f88c7f
Packit Service f88c7f
def die(*args, **kwargs):
Packit Service f88c7f
    print(*args, **kwargs)
Packit Service f88c7f
    exit(1)
Packit Service f88c7f
Packit Service f88c7f
def list_to_c_source(worklist, fnc_prefix, width=0):
Packit Service f88c7f
    ret = []
Packit Service f88c7f
Packit Service f88c7f
    while worklist:
Packit Service f88c7f
        item = worklist.pop()
Packit Service f88c7f
        if type(item) is list:
Packit Service f88c7f
            head, children = item
Packit Service f88c7f
            if type(children) is list:
Packit Service f88c7f
                for i, ci in enumerate(children):
Packit Service f88c7f
                    ret += list_to_c_source([ci], fnc_prefix, width)
Packit Service f88c7f
                    if type(ci) is list:
Packit Service f88c7f
                        children[i] = ci[0]
Packit Service f88c7f
                        if type(children[i]) is list:
Packit Service f88c7f
                            children[i] = children[i][0]
Packit Service f88c7f
        else:
Packit Service f88c7f
            head = item
Packit Service f88c7f
            children = []
Packit Service f88c7f
        if type(head) is not list:
Packit Service f88c7f
            head = [head]
Packit Service f88c7f
        ret += ["static void {0}_{1:0{2}}(int doit) {{"
Packit Service f88c7f
                .format(fnc_prefix, head[0], width),
Packit Service f88c7f
                "\tif (!doit) return;"]
Packit Service f88c7f
        ret += ["\tqb_log(LOG_ERR, \"{0:0{1}}\");".format(i, width)
Packit Service f88c7f
                for i in head]
Packit Service f88c7f
        ret += ["\t{0}_{1:0{2}}(doit);".format(fnc_prefix, i, width)
Packit Service f88c7f
                for i in reversed(children)]
Packit Service f88c7f
        ret += ["}"]
Packit Service f88c7f
    return ret
Packit Service f88c7f
Packit Service f88c7f
def main(opts, args):
Packit Service f88c7f
    FNC_PREFIX = "fnc"
Packit Service f88c7f
Packit Service f88c7f
    try:
Packit Service f88c7f
        CALLSITE_COUNT = int(opts["CALLSITE_COUNT"])
Packit Service f88c7f
        if not 0 < CALLSITE_COUNT < 10 ** 6: raise ValueError
Packit Service f88c7f
    except ValueError:
Packit Service f88c7f
        die("callsites count can only be a number x, 0 < x < 1e6")
Packit Service f88c7f
    try:
Packit Service f88c7f
        BRANCHING_FACTOR = int(opts["BRANCHING_FACTOR"])
Packit Service f88c7f
        if not 0 < BRANCHING_FACTOR < 10 ** 3: raise ValueError
Packit Service f88c7f
    except ValueError:
Packit Service f88c7f
        die("branching factor can only be a number x, 0 < x < 1000")
Packit Service f88c7f
    try:
Packit Service f88c7f
        CALLSITES_PER_FNC = int(opts["CALLSITES_PER_FNC"])
Packit Service f88c7f
        if not 0 < CALLSITES_PER_FNC < 10 ** 3: raise ValueError
Packit Service f88c7f
    except ValueError:
Packit Service f88c7f
        die("callsites-per-fnc count can only be a number x, 0 < x < 1000")
Packit Service f88c7f
    try:
Packit Service f88c7f
        ROUND_COUNT = int(opts["ROUND_COUNT"])
Packit Service f88c7f
        if not 0 < ROUND_COUNT < 10 ** 6: raise ValueError
Packit Service f88c7f
    except ValueError:
Packit Service f88c7f
        die("round count can only be a number x, 0 < x < 1e6")
Packit Service f88c7f
Packit Service f88c7f
    worklist, worklist_len = list(range(0, CALLSITE_COUNT)), CALLSITE_COUNT
Packit Service f88c7f
    #shuffle(worklist)
Packit Service f88c7f
Packit Service f88c7f
    #pprint(worklist)
Packit Service f88c7f
    first = worklist[0]
Packit Service f88c7f
    while worklist_len > 1:
Packit Service f88c7f
        item = worklist.pop(); worklist_len -= 1
Packit Service f88c7f
        reminder = worklist_len % CALLSITES_PER_FNC
Packit Service f88c7f
        parent = (worklist_len - reminder if reminder
Packit Service f88c7f
                  else (worklist_len // CALLSITES_PER_FNC - 1)
Packit Service f88c7f
                        // BRANCHING_FACTOR * CALLSITES_PER_FNC)
Packit Service f88c7f
        #print("parent {0} (len={1})".format(parent, worklist_len))
Packit Service f88c7f
        if type(worklist[parent]) is not list:
Packit Service f88c7f
            worklist[parent] = [worklist[parent], []]
Packit Service f88c7f
        if not(reminder):
Packit Service f88c7f
            worklist[parent][1].append(item)  # reverses the order!
Packit Service f88c7f
            #worklist[parent][1][:0] = [item]
Packit Service f88c7f
        else:
Packit Service f88c7f
            if type(worklist[parent][0]) is not list:
Packit Service f88c7f
                worklist[parent][0] = [worklist[parent][0]]
Packit Service f88c7f
            #worklist[parent][0].append(item)  # reverses the order
Packit Service f88c7f
            worklist[parent][0][1:1] = [item]  # parent itself the 1st element
Packit Service f88c7f
        #pprint(worklist)
Packit Service f88c7f
Packit Service f88c7f
    width = int(floor(log10(CALLSITE_COUNT))) + 1
Packit Service f88c7f
    print('\n'.join([
Packit Service f88c7f
        "/* compile with -lqb OR with -DQB_KILL_ATTRIBUTE_SECTION -l:libqb.so.0 */",
Packit Service f88c7f
        "#include <qb/qblog.h>",
Packit Service f88c7f
    ] + list_to_c_source(worklist, FNC_PREFIX, width) + [
Packit Service f88c7f
        "int main(int argc, char *argv[]) {",
Packit Service f88c7f
        "\tqb_log_init(\"log_gen_test\", LOG_DAEMON, LOG_INFO);",
Packit Service f88c7f
        "\tqb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);",
Packit Service f88c7f
        "\tqb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, \"*\", LOG_ERR);",
Packit Service f88c7f
        "\tqb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);",
Packit Service f88c7f
        "\tfor (int i = 0; i < {0}; i++) {{".format(ROUND_COUNT),
Packit Service f88c7f
        "\t\t{0}_{1:0{2}}(argc);".format(FNC_PREFIX, first, width),
Packit Service f88c7f
        "\t}",
Packit Service f88c7f
        "\tqb_log_fini();",
Packit Service f88c7f
        "\treturn !argc;",
Packit Service f88c7f
        "}"
Packit Service f88c7f
    ]
Packit Service f88c7f
    ))
Packit Service f88c7f
Packit Service f88c7f
Packit Service f88c7f
if __name__ == '__main__':
Packit Service f88c7f
    # Full trees for CALLSITES_PER_FNC == 1 (can be trivially extrapolated):
Packit Service f88c7f
    # BF = 2 (binary trees)
Packit Service f88c7f
    # --> C = 7 (3 steps), 15 (4 steps), ..., 127 (6 steps), ...
Packit Service f88c7f
    #     (see https://en.wikipedia.org/wiki/Binary_tree#Properties_of_binary_trees)
Packit Service f88c7f
    # BF = 3 (ternary trees)
Packit Service f88c7f
    # --> C = 13 (3 steps), 40 (4 steps), ..., 1093 (6 steps), ...
Packit Service f88c7f
    #     (see https://en.wikipedia.org/wiki/Ternary_tree#Properties_of_ternary_trees)
Packit Service f88c7f
    # ...
Packit Service f88c7f
    BRANCHING_FACTOR = 3
Packit Service f88c7f
    CALLSITES_PER_FNC = 10
Packit Service f88c7f
    CALLSITE_COUNT = 3640
Packit Service f88c7f
    ROUND_COUNT = 1000
Packit Service f88c7f
    try:
Packit Service f88c7f
        opts, args = getopt(argv[1:],
Packit Service f88c7f
                             "hc:b:f:r:",
Packit Service f88c7f
                            ("help", "callsite-count=", "branching-factor=",
Packit Service f88c7f
                             "callsites-per-fnc=", "round-count="))
Packit Service f88c7f
        for o, a in opts:
Packit Service f88c7f
            if o in ("-h", "--help"):
Packit Service f88c7f
                raise GetoptError("__justhelp__")
Packit Service f88c7f
            elif o in ("-c", "--callsite-count"): CALLSITE_COUNT = a
Packit Service f88c7f
            elif o in ("-b", "--branching-factor"): BRANCHING_FACTOR = a
Packit Service f88c7f
            elif o in ("-f", "--callsites-per-fnc"): CALLSITES_PER_FNC = a
Packit Service f88c7f
            elif o in ("-r", "--round-count"): ROUND_COUNT = a
Packit Service f88c7f
    except GetoptError as err:
Packit Service f88c7f
        if err.msg != "__justhelp__":
Packit Service f88c7f
            print(str(err))
Packit Service f88c7f
        print("Usage:\n{0} -h|--help\n"
Packit Service f88c7f
              "{0} [-c X|--callsite-count={CALLSITE_COUNT}]"
Packit Service f88c7f
              " [-b Y|--branching-factor={BRANCHING_FACTOR}]\n"
Packit Service f88c7f
              "{1:{2}} [-f Z|--callsites-per-fnc={CALLSITES_PER_FNC}]"
Packit Service f88c7f
              " [-r R|--round-count={ROUND_COUNT}]"
Packit Service f88c7f
              .format(argv[0], '', len(argv[0]), **locals()))
Packit Service f88c7f
        exit(0 if err.msg == "__justhelp__" else 2)
Packit Service f88c7f
Packit Service f88c7f
    opts = dict(CALLSITE_COUNT=CALLSITE_COUNT,
Packit Service f88c7f
                BRANCHING_FACTOR=BRANCHING_FACTOR,
Packit Service f88c7f
                CALLSITES_PER_FNC=CALLSITES_PER_FNC,
Packit Service f88c7f
                ROUND_COUNT=ROUND_COUNT)
Packit Service f88c7f
    main(opts, args)