diff --git a/mixnet/v2/sim/analysis.py b/mixnet/v2/sim/analysis.py index 23108eb..91a4226 100644 --- a/mixnet/v2/sim/analysis.py +++ b/mixnet/v2/sim/analysis.py @@ -22,47 +22,47 @@ class Analysis: def bandwidth(self, message_size_df: pd.DataFrame): dataframes = [] - nonzero_ingresses = [] nonzero_egresses = [] - for ingress_bandwidths, egress_bandwidths in zip(self.sim.p2p.measurement.ingress_bandwidth_per_time, - self.sim.p2p.measurement.egress_bandwidth_per_time): + nonzero_ingresses = [] + for egress_bandwidths, ingress_bandwidths in zip(self.sim.p2p.measurement.egress_bandwidth_per_time, + self.sim.p2p.measurement.ingress_bandwidth_per_time): rows = [] for node in self.sim.p2p.nodes: - ingress = ingress_bandwidths[node] / 1024.0 egress = egress_bandwidths[node] / 1024.0 - rows.append((node.id, ingress, egress)) - if ingress > 0: - nonzero_ingresses.append(ingress) + ingress = ingress_bandwidths[node] / 1024.0 + rows.append((node.id, egress, ingress)) if egress > 0: nonzero_egresses.append(egress) - df = pd.DataFrame(rows, columns=["node_id", "ingress", "egress"]) + if ingress > 0: + nonzero_ingresses.append(ingress) + df = pd.DataFrame(rows, columns=["node_id", "egress", "ingress"]) dataframes.append(df) times = range(len(dataframes)) df = pd.concat([df.assign(Time=time) for df, time in zip(dataframes, times)], ignore_index=True) - df = df.pivot(index="Time", columns="node_id", values=["ingress", "egress"]) + df = df.pivot(index="Time", columns="node_id", values=["egress", "ingress"]) plt.figure(figsize=(12, 6)) for column in df.columns: marker = "x" if column[0] == "ingress" else "o" plt.plot(df.index, df[column], marker=marker, label=column[0]) - plt.title("Ingress/egress bandwidth of each node over time") + plt.title("Egress/ingress bandwidth of each node over time") plt.xlabel("Time") plt.ylabel("Bandwidth (KiB/s)") plt.ylim(bottom=0) - # Customize the legend to show only 'ingress' and 'egress' regardless of node_id + # Customize the legend to show only 'egress' and 'ingress' regardless of node_id handles, labels = plt.gca().get_legend_handles_labels() by_label = dict(zip(labels, handles)) plt.legend(by_label.values(), by_label.keys()) plt.grid(True) # Adding descriptions on the right size of the plot - ingress_series = pd.Series(nonzero_ingresses) egress_series = pd.Series(nonzero_egresses) + ingress_series = pd.Series(nonzero_ingresses) desc = ( f"message: {message_size_df["message_size"].mean():.0f} bytes\n" f"{self.config.description()}\n\n" - f"[ingress(>0)]\nmean: {ingress_series.mean():.2f} KiB/s\nmax: {ingress_series.max():.2f} KiB/s\n\n" - f"[egress(>0)]\nmean: {egress_series.mean():.2f} KiB/s\nmax: {egress_series.max():.2f} KiB/s" + f"[egress(>0)]\nmean: {egress_series.mean():.2f} KiB/s\nmax: {egress_series.max():.2f} KiB/s\n\n" + f"[ingress(>0)]\nmean: {ingress_series.mean():.2f} KiB/s\nmax: {ingress_series.max():.2f} KiB/s" ) plt.text(1.02, 0.5, desc, transform=plt.gca().transAxes, verticalalignment="center", fontsize=12) plt.subplots_adjust(right=0.8) # Adjust layout to make room for the text diff --git a/mixnet/v2/sim/bulk_run.py b/mixnet/v2/sim/bulk_run.py index 432f830..52bf6d6 100644 --- a/mixnet/v2/sim/bulk_run.py +++ b/mixnet/v2/sim/bulk_run.py @@ -37,14 +37,14 @@ def bulk_run(): sim = Simulation(config) sim.run() - ingress, egress = sim.p2p.measurement.bandwidth() + egress, ingress = sim.p2p.measurement.bandwidth() results.append({ "num_nodes": num_nodes, "config": f"{p2p_type}: {num_mix_layers}: {cover_message_prob}", - "ingress_mean": ingress.mean(), - "ingress_max": ingress.max(), "egress_mean": egress.mean(), "egress_max": egress.max(), + "ingress_mean": ingress.mean(), + "ingress_max": ingress.max(), }) df = pd.DataFrame(results) @@ -60,38 +60,6 @@ def load_and_plot(): def plot(df: pd.DataFrame): - ingress_max_df = df.pivot(index='num_nodes', columns='config', values='ingress_max') - plt.figure(figsize=(12, 6)) - fig, ax = plt.subplots() - for config in ingress_max_df.columns: - num_mix_layers = int(config.split(":")[1].strip()) - ax.plot(ingress_max_df.index, ingress_max_df[config], label=config, - marker=MARKERS[NUM_MIX_LAYERS_SET.index(num_mix_layers)]) - plt.title("Ingress Bandwidth (Max)") - plt.xlabel("Number of Nodes") - plt.ylabel("Max Bandwidth (KiB/s)") - plt.legend(title="mode: layers: cover", loc="upper left") - plt.tight_layout() - plt.grid(True) - plt.show() - ingress_max_y_lim = ax.get_ylim() - - ingress_mean_df = df.pivot(index='num_nodes', columns='config', values='ingress_mean') - plt.figure(figsize=(12, 6)) - fig, ax = plt.subplots() - for config in ingress_mean_df.columns: - num_mix_layers = int(config.split(":")[1].strip()) - ax.plot(ingress_mean_df.index, ingress_mean_df[config], label=config, - marker=MARKERS[NUM_MIX_LAYERS_SET.index(num_mix_layers)]) - plt.title("Ingress Bandwidth (Mean)") - plt.xlabel("Number of Nodes") - plt.ylabel("Mean Bandwidth (KiB/s)") - plt.legend(title="mode: layers: cover", loc="upper left") - plt.tight_layout() - plt.grid(True) - ax.set_ylim(ingress_max_y_lim) - plt.show() - egress_max_df = df.pivot(index='num_nodes', columns='config', values='egress_max') plt.figure(figsize=(12, 6)) fig, ax = plt.subplots() @@ -124,6 +92,38 @@ def plot(df: pd.DataFrame): ax.set_ylim(ingress_max_y_lim) plt.show() + ingress_max_df = df.pivot(index='num_nodes', columns='config', values='ingress_max') + plt.figure(figsize=(12, 6)) + fig, ax = plt.subplots() + for config in ingress_max_df.columns: + num_mix_layers = int(config.split(":")[1].strip()) + ax.plot(ingress_max_df.index, ingress_max_df[config], label=config, + marker=MARKERS[NUM_MIX_LAYERS_SET.index(num_mix_layers)]) + plt.title("Ingress Bandwidth (Max)") + plt.xlabel("Number of Nodes") + plt.ylabel("Max Bandwidth (KiB/s)") + plt.legend(title="mode: layers: cover", loc="upper left") + plt.tight_layout() + plt.grid(True) + plt.show() + ingress_max_y_lim = ax.get_ylim() + + ingress_mean_df = df.pivot(index='num_nodes', columns='config', values='ingress_mean') + plt.figure(figsize=(12, 6)) + fig, ax = plt.subplots() + for config in ingress_mean_df.columns: + num_mix_layers = int(config.split(":")[1].strip()) + ax.plot(ingress_mean_df.index, ingress_mean_df[config], label=config, + marker=MARKERS[NUM_MIX_LAYERS_SET.index(num_mix_layers)]) + plt.title("Ingress Bandwidth (Mean)") + plt.xlabel("Number of Nodes") + plt.ylabel("Mean Bandwidth (KiB/s)") + plt.legend(title="mode: layers: cover", loc="upper left") + plt.tight_layout() + plt.grid(True) + ax.set_ylim(ingress_max_y_lim) + plt.show() + if __name__ == "__main__": bulk_run() diff --git a/mixnet/v2/sim/measurement.py b/mixnet/v2/sim/measurement.py index f9b258e..fa9a641 100644 --- a/mixnet/v2/sim/measurement.py +++ b/mixnet/v2/sim/measurement.py @@ -10,21 +10,22 @@ from sphinx import SphinxPacket if TYPE_CHECKING: from node import Node + class Measurement: def __init__(self, env: simpy.Environment, config: Config): self.env = env self.config = config - self.ingress_bandwidth_per_time = [] self.egress_bandwidth_per_time = [] + self.ingress_bandwidth_per_time = [] self.env.process(self._update_bandwidth_window()) - def measure_ingress(self, node: "Node", msg: SphinxPacket | bytes): - self.ingress_bandwidth_per_time[-1][node] += len(msg) - def measure_egress(self, node: "Node", msg: SphinxPacket | bytes): self.egress_bandwidth_per_time[-1][node] += len(msg) + def measure_ingress(self, node: "Node", msg: SphinxPacket | bytes): + self.ingress_bandwidth_per_time[-1][node] += len(msg) + def _update_bandwidth_window(self): while True: self.ingress_bandwidth_per_time.append(defaultdict(int)) @@ -32,12 +33,13 @@ class Measurement: yield self.env.timeout(self.config.measurement.sim_time_per_second) def bandwidth(self) -> (pd.Series, pd.Series): - nonzero_ingresses, nonzero_egresses = [], [] - for ingress_bandwidths, egress_bandwidths in zip(self.ingress_bandwidth_per_time, self.egress_bandwidth_per_time): - for bandwidth in ingress_bandwidths.values(): - if bandwidth > 0: - nonzero_ingresses.append(bandwidth / 1024.0) + nonzero_egresses, nonzero_ingresses = [], [] + for egress_bandwidths, ingress_bandwidths in zip(self.egress_bandwidth_per_time, + self.ingress_bandwidth_per_time): for bandwidth in egress_bandwidths.values(): if bandwidth > 0: nonzero_egresses.append(bandwidth / 1024.0) - return pd.Series(nonzero_ingresses), pd.Series(nonzero_egresses) + for bandwidth in ingress_bandwidths.values(): + if bandwidth > 0: + nonzero_ingresses.append(bandwidth / 1024.0) + return pd.Series(nonzero_egresses), pd.Series(nonzero_ingresses)