import asyncio import logging import os import random import string import threading import time from socketio.server import SocketServer from socketio.client import SocketClient class PerformanceTest: def __init__(self): self.terminate = False self._server = None self._socket_client = None self.received_messages = 0 self.sended_messages = 0 self.conditions = [] self.cps = {"miatel": 7, "comlink": 7, "spacetel": 7} operators = {"miatel": 14, "comlink": 10, "spacetel": 4} self.resources = {} self.call_delays = {} self.last_call_at = {} self.call_locks = {} for key, value in self.cps.items(): self.call_delays[key] = 1.0 / float(value) self.last_call_at[key] = time.time() self.call_locks[key] = asyncio.Lock() i = 0 k = 0 while i < 15: i += 1 for operator, cnt in operators.items(): j = 0 while j < cnt: j += 1 k += 1 self.resources[k] = {"conditions": [], "is_busy": 0, "cs": threading.Lock(), "operator": operator} self.timings = [] @asyncio.coroutine def run(self): while not self.terminate: yield from asyncio.sleep(1) def create_server(self): loop = asyncio.get_event_loop() path = os.path.dirname(os.path.abspath(__file__)) self._server = SocketServer({"test": self.test_server, "test_waiting": self.test_waiting}, path + '/configs/socket_server.ini') loop.run_until_complete(self.run()) def create_client(self): loop = asyncio.get_event_loop() self._socket_client = SocketClient(["127.0.0.1", "54445"], {"test": self.test_client, "action1": self.action1}) loop.create_task(self._socket_client.connector()) loop.run_until_complete(self.run()) def take_resource(self): timed_out = False message_showed = False time_out = 300 while not timed_out: for resource_id, resource in self.resources.items(): resource["cs"].acquire() if not resource["is_busy"]: resource["is_busy"] = 1 resource["cs"].release() return resource_id, resource["operator"] resource["cs"].release() if not message_showed: print("all resources as busy, wait") message_showed = True condition = threading.Condition() with condition: self.conditions.append(condition) timed_out = not condition.wait(time_out) raise Exception("failed to take resource") def release_resource(self, resource_id): resource = self.resources[resource_id] resource["is_busy"] = 0 if len(self.conditions) > 0: condition = self.conditions.pop(0) with condition: condition.notify() resource["conditions"] = [] def sending_as_client(self, message, count=1, length=16, timeout=0.1, with_wait=False): if self._socket_client is not None: counter = 0 while counter < count: counter += 1 self.sended_messages += 1 if with_wait: print("start waiting for response") time1 = time.time() self._socket_client.append_message({"action": "test_waiting", "test": message, "time": time.time()}, True) print("waiting response time: %f" % (time.time() - time1)) time.sleep(timeout) else: resource_id, operator = self.take_resource() self._socket_client.append_message({"action": "test", "test": message, "time": time.time(), "resource_id": resource_id, "operator": operator}) time.sleep(timeout) else: print("ERROR! no client exists!") def server_worker(self, message): repeat_cnt = random.choice([0, 1, 2, 3]) i = 0 while i < repeat_cnt: i += 1 sleep_time = random.choice([1, 2, 0, 1, 1, 4, 1, 3, 2, 5, 10]) time.sleep(sleep_time) self._server.broadcast_message({"action": "action1", "test": message["test"]}) sleep_time = random.choice([1, 2, 0, 1, 1, 4, 1, 3, 2, 5]) time.sleep(sleep_time) self._server.broadcast_message(message) @asyncio.coroutine def test_server(self, message): print("receiving time: %f" % (time.time() - message["time"])) self.timings.append(time.time() - message["time"]) self.received_messages += 1 with (yield from self.call_locks[message["operator"]]): current_delay = time.time() - self.last_call_at[message["operator"]] if current_delay < self.call_delays[message["operator"]]: yield from asyncio.sleep(self.call_delays[message["operator"]] - current_delay) self.last_call_at[message["operator"]] = time.time() worker_thread = threading.Thread(target=self.server_worker, args=(message,)) worker_thread.daemon = True worker_thread.start() @asyncio.coroutine def test_waiting(self, message): print("receive waiting time: %f" % (time.time() - message["time"])) self.timings.append(time.time() - message["time"]) self.received_messages += 1 time.sleep(5) return {"action": "test_waiting", "response": "success"} @asyncio.coroutine def test_client(self, message): self.timings.append(time.time() - message["time"]) self.received_messages += 1 self.release_resource(message["resource_id"]) @asyncio.coroutine def action1(self, message): action_tread = threading.Thread(target=self._action_worker) action_tread.daemon = True action_tread.start() def _action_worker(self): sleep_time = random.choice([1, 2, 0, 1, 1, 4, 12, 8, 3, 5]) time.sleep(sleep_time)