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
This commit is contained in:
Ilya Shakhat 2016-03-02 19:06:16 +03:00
parent d2496c34d9
commit 97385ef5b5
1 changed files with 23 additions and 15 deletions

View File

@ -14,6 +14,7 @@ import eventlet
eventlet.monkey_patch() eventlet.monkey_patch()
import argparse import argparse
import bisect
import collections import collections
import datetime import datetime
import itertools import itertools
@ -27,8 +28,6 @@ import threading
import time import time
import yaml import yaml
from scipy.stats import rv_discrete
from oslo_config import cfg from oslo_config import cfg
import oslo_messaging as messaging import oslo_messaging as messaging
from oslo_messaging import notify # noqa from oslo_messaging import notify # noqa
@ -36,7 +35,7 @@ from oslo_messaging import rpc # noqa
from oslo_utils import timeutils from oslo_utils import timeutils
LOG = logging.getLogger() LOG = logging.getLogger()
RANDOM_VARIABLE = None RANDOM_GENERATOR = None
CURRENT_PID = None CURRENT_PID = None
RPC_CLIENTS = [] RPC_CLIENTS = []
MESSAGES = [] MESSAGES = []
@ -51,6 +50,8 @@ Usage example:
--url rabbit://stackrabbit:secretrabbit@localhost/ rpc-client\ --url rabbit://stackrabbit:secretrabbit@localhost/ rpc-client\
--exit-wait 15000 -p 64 -m 64""" --exit-wait 15000 -p 64 -m 64"""
DISTRIBUTION_BUCKET_SIZE = 500
def init_random_generator(): def init_random_generator():
data = [] data = []
@ -61,18 +62,26 @@ def init_random_generator():
ranges = collections.defaultdict(int) ranges = collections.defaultdict(int)
for msg_length in data: 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[range_start] += 1
ranges_start = sorted(ranges.keys()) ranges_start = sorted(ranges.keys())
total_count = len(data) 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)) accumulated_distribution = []
return random_var 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): class LoggingNoParsingFilter(logging.Filter):
@ -214,10 +223,9 @@ def init_msg(messages_count):
if messages_count > 1000: if messages_count > 1000:
messages_count = 1000 messages_count = 1000
LOG.info("Preparing %d messages", messages_count) LOG.info("Preparing %d messages", messages_count)
ranges = RANDOM_VARIABLE.rvs(size=messages_count)
i = 0 for i in range(messages_count):
for range_start in ranges: length = RANDOM_GENERATOR()
length = random.randint(range_start, range_start + 497)
msg = ''.join(random.choice(string.lowercase) for x in range(length)) \ msg = ''.join(random.choice(string.lowercase) for x in range(length)) \
+ ' ' + str(i) + ' ' + str(i)
MESSAGES.append(msg) MESSAGES.append(msg)
@ -472,6 +480,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
RANDOM_VARIABLE = init_random_generator() RANDOM_GENERATOR = init_random_generator()
CURRENT_PID = os.getpid() CURRENT_PID = os.getpid()
main() main()