From 97385ef5b5889c0b4eb7cbbe3323c26fed021e54 Mon Sep 17 00:00:00 2001 From: Ilya Shakhat Date: Wed, 2 Mar 2016 19:06:16 +0300 Subject: [PATCH] Simulator: implement own random generator instead of scipy Dependency on scipy results in extra requirements to the system (include the need of Fortran compiler). With this patch the weighted random choice algorithm is implemented directly. Change-Id: I60cbc6c452945000add5a65263d1ab4e42dd91f9 --- tools/simulator.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/tools/simulator.py b/tools/simulator.py index 72679b791..f77e58ce3 100755 --- a/tools/simulator.py +++ b/tools/simulator.py @@ -14,6 +14,7 @@ import eventlet eventlet.monkey_patch() import argparse +import bisect import collections import datetime import itertools @@ -27,8 +28,6 @@ import threading import time import yaml -from scipy.stats import rv_discrete - from oslo_config import cfg import oslo_messaging as messaging from oslo_messaging import notify # noqa @@ -36,7 +35,7 @@ from oslo_messaging import rpc # noqa from oslo_utils import timeutils LOG = logging.getLogger() -RANDOM_VARIABLE = None +RANDOM_GENERATOR = None CURRENT_PID = None RPC_CLIENTS = [] MESSAGES = [] @@ -51,6 +50,8 @@ Usage example: --url rabbit://stackrabbit:secretrabbit@localhost/ rpc-client\ --exit-wait 15000 -p 64 -m 64""" +DISTRIBUTION_BUCKET_SIZE = 500 + def init_random_generator(): data = [] @@ -61,18 +62,26 @@ def init_random_generator(): ranges = collections.defaultdict(int) for msg_length in data: - range_start = (msg_length / 500) * 500 + 1 + range_start = ((msg_length / DISTRIBUTION_BUCKET_SIZE) * + DISTRIBUTION_BUCKET_SIZE + 1) ranges[range_start] += 1 ranges_start = sorted(ranges.keys()) total_count = len(data) - ranges_dist = [] - for r in ranges_start: - r_dist = float(ranges[r]) / total_count - ranges_dist.append(r_dist) - random_var = rv_discrete(values=(ranges_start, ranges_dist)) - return random_var + accumulated_distribution = [] + running_total = 0 + for range_start in ranges_start: + norm = float(ranges[range_start]) / total_count + running_total += norm + accumulated_distribution.append(running_total) + + def weighted_random_choice(): + r = random.random() * running_total + start = ranges_start[bisect.bisect_right(accumulated_distribution, r)] + return random.randrange(start, start + DISTRIBUTION_BUCKET_SIZE) + + return weighted_random_choice class LoggingNoParsingFilter(logging.Filter): @@ -214,10 +223,9 @@ def init_msg(messages_count): if messages_count > 1000: messages_count = 1000 LOG.info("Preparing %d messages", messages_count) - ranges = RANDOM_VARIABLE.rvs(size=messages_count) - i = 0 - for range_start in ranges: - length = random.randint(range_start, range_start + 497) + + for i in range(messages_count): + length = RANDOM_GENERATOR() msg = ''.join(random.choice(string.lowercase) for x in range(length)) \ + ' ' + str(i) MESSAGES.append(msg) @@ -472,6 +480,6 @@ def main(): if __name__ == '__main__': - RANDOM_VARIABLE = init_random_generator() + RANDOM_GENERATOR = init_random_generator() CURRENT_PID = os.getpid() main()