def run(self, bench_parameters_dict, node_parameters_dict, debug=False): assert isinstance(debug, bool) Print.heading('Starting remote benchmark') try: bench_parameters = BenchParameters(bench_parameters_dict) node_parameters = NodeParameters(node_parameters_dict) except ConfigError as e: raise BenchError('Invalid nodes or bench parameters', e) # Select which hosts to use. selected_hosts = self._select_hosts(bench_parameters) if not selected_hosts: Print.warn('There are not enough instances available') return # Update nodes. try: self._update(selected_hosts) except (GroupException, ExecutionError) as e: e = FabricError(e) if isinstance(e, GroupException) else e raise BenchError('Failed to update nodes', e) # Run benchmarks. for n in bench_parameters.nodes: for r in bench_parameters.rate: Print.heading(f'\nRunning {n} nodes (input rate: {r:,} tx/s)') hosts = selected_hosts[:n] # Upload all configuration files. try: self._config(hosts, node_parameters) except (subprocess.SubprocessError, GroupException) as e: e = FabricError(e) if isinstance(e, GroupException) else e Print.error(BenchError('Failed to configure nodes', e)) continue # Run the benchmark. for i in range(bench_parameters.runs): Print.heading(f'Run {i+1}/{bench_parameters.runs}') try: self._run_single(hosts, r, bench_parameters, node_parameters, debug) self._logs(hosts).print( PathMaker.result_file(n, r, bench_parameters.tx_size)) except (subprocess.SubprocessError, GroupException, ParseError) as e: self.kill(hosts=hosts) if isinstance(e, GroupException): e = FabricError(e) Print.error(BenchError('Benchmark failed', e)) continue
def __init__(self, clients, nodes, faults, protocol, ddos): inputs = [clients, nodes] assert all(isinstance(x, list) for x in inputs) assert all(isinstance(x, str) for y in inputs for x in y) assert all(x for x in inputs) self.protocol = protocol self.ddos = ddos self.faults = faults self.committee_size = len(nodes) + faults # Parse the clients logs. try: with Pool() as p: results = p.map(self._parse_clients, clients) except (ValueError, IndexError) as e: raise ParseError(f'Failed to parse client logs: {e}') self.size, self.rate, self.start, misses, self.sent_samples \ = zip(*results) self.misses = sum(misses) # Parse the nodes logs. try: with Pool() as p: results = p.map(self._parse_nodes, nodes) except (ValueError, IndexError) as e: raise ParseError(f'Failed to parse node logs: {e}') proposals, commits, sizes, self.received_samples, timeouts, self.configs \ = zip(*results) self.proposals = self._merge_results([x.items() for x in proposals]) self.commits = self._merge_results([x.items() for x in commits]) self.sizes = { k: v for x in sizes for k, v in x.items() if k in self.commits } self.timeouts = max(timeouts) # Check whether clients missed their target rate. if self.misses != 0: Print.warn( f'Clients missed their target rate {self.misses:,} time(s)') # Check whether the nodes timed out. # Note that nodes are expected to time out once at the beginning. if self.timeouts > 1: Print.warn(f'Nodes timed out {self.timeouts:,} time(s)')
def run(self, bench_parameters_dict, node_parameters_dict, debug=False): assert isinstance(debug, bool) Print.heading('Starting remote benchmark') try: bench_parameters = BenchParameters(bench_parameters_dict) node_parameters = NodeParameters(node_parameters_dict) except ConfigError as e: raise BenchError('Invalid nodes or bench parameters', e) # Select which hosts to use. selected_hosts = self._select_hosts(bench_parameters) if not selected_hosts: Print.warn('There are not enough instances available') return # Update nodes. try: self._update(selected_hosts) except (GroupException, ExecutionError) as e: e = FabricError(e) if isinstance(e, GroupException) else e raise BenchError('Failed to update nodes', e) if node_parameters.protocol == 0: Print.info('Running HotStuff') elif node_parameters.protocol == 1: Print.info('Running AsyncHotStuff') elif node_parameters.protocol == 2: Print.info('Running TwoChainVABA') else: Print.info('Wrong protocol type!') return Print.info(f'{bench_parameters.faults} faults') Print.info( f'Timeout {node_parameters.timeout_delay} ms, Network delay {node_parameters.network_delay} ms' ) Print.info(f'DDOS attack {node_parameters.ddos}') hosts = selected_hosts[:bench_parameters.nodes[0]] # Upload all configuration files. try: self._config(hosts, node_parameters) except (subprocess.SubprocessError, GroupException) as e: e = FabricError(e) if isinstance(e, GroupException) else e Print.error(BenchError('Failed to configure nodes', e)) # Run benchmarks. for n in bench_parameters.nodes: for r in bench_parameters.rate: Print.heading(f'\nRunning {n} nodes (input rate: {r:,} tx/s)') hosts = selected_hosts[:n] # # Upload all configuration files. # try: # self._config(hosts, node_parameters) # except (subprocess.SubprocessError, GroupException) as e: # e = FabricError(e) if isinstance(e, GroupException) else e # Print.error(BenchError('Failed to configure nodes', e)) # continue # Do not boot faulty nodes. faults = bench_parameters.faults hosts = hosts[:n - faults] protocol = node_parameters.protocol ddos = node_parameters.ddos # Run the benchmark. for i in range(bench_parameters.runs): Print.heading(f'Run {i+1}/{bench_parameters.runs}') try: self._run_single(hosts, r, bench_parameters, node_parameters, debug) self._logs(hosts, faults, protocol, ddos).print( PathMaker.result_file(n, r, bench_parameters.tx_size, faults)) except (subprocess.SubprocessError, GroupException, ParseError) as e: self.kill(hosts=hosts) if isinstance(e, GroupException): e = FabricError(e) Print.error(BenchError('Benchmark failed', e)) continue