mirror of
https://github.com/logos-blockchain/logos-blockchain-specs.git
synced 2026-01-03 21:53:07 +00:00
add bulk_run
This commit is contained in:
parent
812061ab60
commit
af94346279
124
mixnet/v2/sim/bulk_run.py
Normal file
124
mixnet/v2/sim/bulk_run.py
Normal file
@ -0,0 +1,124 @@
|
||||
import argparse
|
||||
|
||||
import pandas as pd
|
||||
import seaborn
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from config import P2PConfig, Config
|
||||
from analysis import Analysis
|
||||
from simulation import Simulation
|
||||
|
||||
COL_P2P_TYPE = "P2P Type"
|
||||
COL_NUM_NODES = "Num Nodes"
|
||||
COL_TRAFFIC_TYPE = "Traffic Type"
|
||||
COL_STAT = "Stat"
|
||||
COL_BANDWIDTH = "Bandwidth"
|
||||
|
||||
TRAFFIC_TYPE_INGRESS = "Ingress"
|
||||
TRAFFIC_TYPE_EGRESS = "Egress"
|
||||
STAT_MEAN = "mean"
|
||||
STAT_MAX = "max"
|
||||
|
||||
|
||||
def bulk_run():
|
||||
parser = argparse.ArgumentParser(description="Run simulation",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument("--config", type=str, required=True, help="Configuration file path")
|
||||
args = parser.parse_args()
|
||||
config = Config.load(args.config)
|
||||
|
||||
data = {
|
||||
COL_P2P_TYPE: [],
|
||||
COL_NUM_NODES: [],
|
||||
COL_TRAFFIC_TYPE: [],
|
||||
COL_STAT: [],
|
||||
COL_BANDWIDTH: [],
|
||||
}
|
||||
|
||||
message_size_df = None
|
||||
|
||||
for p2p_type in [P2PConfig.TYPE_ONE_TO_ALL, P2PConfig.TYPE_GOSSIP]:
|
||||
config.p2p.type = p2p_type
|
||||
for num_nodes in [10, 100, 1000]:
|
||||
config.mixnet.num_nodes = num_nodes
|
||||
sim = Simulation(config)
|
||||
sim.run()
|
||||
if message_size_df is None:
|
||||
message_size_df = Analysis(sim, config).message_size_distribution()
|
||||
|
||||
nonzero_ingresses, nonzero_egresses = [], []
|
||||
for ingress_bandwidths, egress_bandwidths in zip(sim.p2p.measurement.ingress_bandwidth_per_time,
|
||||
sim.p2p.measurement.egress_bandwidth_per_time):
|
||||
for node in sim.p2p.nodes:
|
||||
ingress = ingress_bandwidths[node] / 1024.0
|
||||
egress = egress_bandwidths[node] / 1024.0
|
||||
if ingress > 0:
|
||||
nonzero_ingresses.append(ingress)
|
||||
if egress > 0:
|
||||
nonzero_egresses.append(egress)
|
||||
|
||||
ingresses = pd.Series(nonzero_ingresses)
|
||||
add_data(data, p2p_type, num_nodes, TRAFFIC_TYPE_INGRESS, STAT_MEAN, ingresses.mean())
|
||||
add_data(data, p2p_type, num_nodes, TRAFFIC_TYPE_INGRESS, STAT_MAX, ingresses.max())
|
||||
egresses = pd.Series(nonzero_egresses)
|
||||
add_data(data, p2p_type, num_nodes, TRAFFIC_TYPE_EGRESS, STAT_MEAN, egresses.mean())
|
||||
add_data(data, p2p_type, num_nodes, TRAFFIC_TYPE_EGRESS, STAT_MAX, egresses.max())
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
draw_bandwidth_plot(df, TRAFFIC_TYPE_INGRESS, config, message_size_df)
|
||||
draw_bandwidth_plot(df, TRAFFIC_TYPE_EGRESS, config, message_size_df)
|
||||
|
||||
|
||||
def add_data(data: dict, p2p_type: str, num_nodes: int, bandwidth_type: str, stat: str, bandwidth: float):
|
||||
data[COL_P2P_TYPE].append(p2p_type)
|
||||
data[COL_NUM_NODES].append(num_nodes)
|
||||
data[COL_TRAFFIC_TYPE].append(bandwidth_type)
|
||||
data[COL_STAT].append(stat)
|
||||
data[COL_BANDWIDTH].append(bandwidth)
|
||||
|
||||
|
||||
def draw_bandwidth_plot(df: pd.DataFrame, traffic_type: str, config: Config, message_size_df: pd.DataFrame):
|
||||
ingress_df = df[df[COL_TRAFFIC_TYPE] == traffic_type]
|
||||
|
||||
plt.figure(figsize=(12, 6))
|
||||
|
||||
mean_df = ingress_df[ingress_df[COL_STAT] == STAT_MEAN]
|
||||
seaborn.barplot(data=mean_df, x=COL_NUM_NODES, y=COL_BANDWIDTH, hue=COL_P2P_TYPE, ax=plt.gca(), capsize=0.1)
|
||||
max_df = ingress_df[ingress_df[COL_STAT] == STAT_MAX]
|
||||
barplot = seaborn.barplot(data=max_df, x=COL_NUM_NODES, y=COL_BANDWIDTH, hue=COL_P2P_TYPE, ax=plt.gca(),
|
||||
capsize=0.1, alpha=0.5)
|
||||
|
||||
# Adding labels to each bar
|
||||
for p in barplot.patches:
|
||||
height = p.get_height()
|
||||
if height > 0: # Only label bars with positive height
|
||||
barplot.annotate(format(height, ".2f"),
|
||||
(p.get_x() + p.get_width() / 2., height),
|
||||
ha="center", va="center",
|
||||
xytext=(0, 9),
|
||||
textcoords="offset points")
|
||||
|
||||
plt.title(f"{traffic_type} Bandwidth")
|
||||
plt.xlabel(COL_NUM_NODES)
|
||||
plt.ylabel(f"{COL_BANDWIDTH} (KB/s)")
|
||||
|
||||
# Custom legend to show Mean and Max
|
||||
handles, labels = barplot.get_legend_handles_labels()
|
||||
for i in range(len(labels) // 2):
|
||||
labels[i] = labels[i] + f" ({STAT_MEAN})"
|
||||
for i in range(len(labels) // 2, len(labels)):
|
||||
labels[i] = labels[i] + f" ({STAT_MAX})"
|
||||
plt.legend(handles=handles, labels=labels, loc="upper left")
|
||||
|
||||
desc = (
|
||||
f"message: {message_size_df["message_size"].mean():.0f} bytes\n"
|
||||
f"{config.description()}"
|
||||
)
|
||||
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
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
bulk_run()
|
||||
@ -96,18 +96,18 @@ class MixnetConfig:
|
||||
|
||||
@dataclass
|
||||
class P2PConfig:
|
||||
# Broadcasting type: naive | gossip
|
||||
# Broadcasting type: 1-to-all | gossip
|
||||
type: str
|
||||
# A connection density, only if the type is gossip
|
||||
connection_density: int
|
||||
# A maximum network latency between nodes directly connected with each other
|
||||
max_network_latency: float
|
||||
|
||||
TYPE_NAIVE = "naive"
|
||||
TYPE_ONE_TO_ALL = "1-to-all"
|
||||
TYPE_GOSSIP = "gossip"
|
||||
|
||||
def validate(self):
|
||||
assert self.type in [self.TYPE_NAIVE, self.TYPE_GOSSIP]
|
||||
assert self.type in [self.TYPE_ONE_TO_ALL, self.TYPE_GOSSIP]
|
||||
if self.type == self.TYPE_GOSSIP:
|
||||
assert self.connection_density > 0
|
||||
assert self.max_network_latency >= 0
|
||||
|
||||
@ -22,7 +22,7 @@ class Simulation:
|
||||
@classmethod
|
||||
def init_p2p(cls, env: simpy.Environment, config: Config):
|
||||
match config.p2p.type:
|
||||
case P2PConfig.TYPE_NAIVE:
|
||||
case P2PConfig.TYPE_ONE_TO_ALL:
|
||||
return NaiveBroadcastP2P(env, config)
|
||||
case P2PConfig.TYPE_GOSSIP:
|
||||
return GossipP2P(env, config)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user