import json import os import time # to change the size of the cluster, just change this parameter NUM_MACHINES = 3 # test setup SCENARIOS = ["point_lookup", "create_tx"] DURATION = 300 WORKERS = 6 # constants SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) MEMGRAPH_BINARY = "memgraph" CLIENT_BINARY = "tests/macro_benchmark/card_fraud_client" BINARIES = [MEMGRAPH_BINARY, CLIENT_BINARY] # wrappers class WorkerWrapper: def __init__(self, address, worker): self._address = address self._worker = worker self._tid = worker.get_jail() def get_address(self): return self._address def __getattr__(self, name): if name in ["allocate_file", "read_file", "store_label"]: return getattr(self._worker, name) def func(*args, **kwargs): args = [self._tid] + list(args) return getattr(self._worker, name)(*args, **kwargs) return func class MgCluster: def __init__(self, machine_ids, workers): # create wrappers self._master = WorkerWrapper(os.environ[machine_ids[0]], workers[machine_ids[0]]) self._workers = [] for machine_id in machine_ids[1:]: self._workers.append(WorkerWrapper(os.environ[machine_id], workers[machine_id])) def start(self): # start memgraph master self._master.start(MEMGRAPH_BINARY, [ "--master", "--master-host", self._master.get_address(), "--master-port", "10000", "--durability-directory", os.path.join(SCRIPT_DIR, "snapshots", "worker_0"), "--db-recover-on-startup", "--query-vertex-count-to-expand-existing", "-1", "--num-workers", str(WORKERS), "--rpc-num-workers", str(WORKERS), ]) # sleep to allow the master to startup time.sleep(5) # start memgraph workers for i, worker in enumerate(self._workers, start=1): worker.start(MEMGRAPH_BINARY, [ "--worker", "--worker-id", str(i), "--worker-host", worker.get_address(), "--worker-port", str(10000 + i), "--master-host", self._master.get_address(), "--master-port", "10000", "--durability-directory", os.path.join(SCRIPT_DIR, "snapshots", "worker_" + str(i)), "--db-recover-on-startup", "--num-workers", str(WORKERS), "--rpc-num-workers", str(WORKERS), ]) # sleep to allow the workers to startup time.sleep(5) # store initial usage self._usage_start = [self._master.get_usage()] for worker in self._workers: self._usage_start.append(worker.get_usage()) self._usage_start_time = time.time() def get_master_address(self): return self._master.get_address() def check_status(self): if not self._master.check_status(): return False for worker in self._workers: if not worker.check_status(): return False return True def stop(self): # store final usage self._usage_stop = [self._master.get_usage()] for worker in self._workers: self._usage_stop.append(worker.get_usage()) self._usage_stop_time = time.time() # stop the master self._master.stop() # wait to allow the master and workers to die time.sleep(5) # stop the workers for worker in self._workers: worker.stop() # wait to allow the workers to die time.sleep(5) def get_usage(self): ret = [] tdelta = self._usage_stop_time - self._usage_start_time for val_start, val_stop in zip(self._usage_start, self._usage_stop): data = { "cpu": (val_stop["cpu"] - val_start["cpu"]) / tdelta, "memory": val_stop["max_memory"] / 1024, "threads": val_stop["max_threads"], "network": {} } net_start = val_start["network"]["eth0"] net_stop = val_stop["network"]["eth0"] for i in ["bytes", "packets"]: data["network"][i] = {} for j in ["rx", "tx"]: data["network"][i][j] = (net_stop[i][j] - net_start[i][j]) / tdelta ret.append(data) return ret def store_label(self, label): self._master.store_label(label) for worker in self._workers: worker.store_label(label) def write_scenario_summary(scenario, throughput, usage, output): output.write("Scenario **{}** throughput !!{:.2f}!! queries/s.\n\n".format( scenario, throughput)) headers = ["Memgraph", "CPU", "Max memory", "Max threads", "Network RX", "Network TX"] output.write("
{} | ".format(header)) output.write("||
---|---|---|
{} | ".format(name)) for key, unit in [("cpu", "s/s"), ("memory", "MiB"), ("threads", "")]: fmt = ".2f" if key != "threads" else "" output.write(("{:" + fmt + "} {} | ").format( current[key], unit).strip()) for key in ["rx", "tx"]: output.write("{:.2f} packets/s | ".format( current["network"]["packets"][key])) output.write("