97 lines
3.8 KiB
Python
Raw Normal View History

from itertools import islice
from pathlib import Path
from typing import List
from pydantic import BaseModel, Field, model_validator, HttpUrl
from torrentool.torrent import Torrent
from urllib3.util import parse_url
from benchmarks.core.config import ExperimentBuilder
from benchmarks.core.experiments.experiments import IteratedExperiment, ExperimentEnvironment, BoundExperiment
from benchmarks.core.experiments.static_experiment import StaticDisseminationExperiment
from benchmarks.core.pydantic import Host
from benchmarks.core.utils import sample, RandomTempData
2024-11-28 17:17:26 -03:00
from benchmarks.deluge.deluge_node import DelugeMeta, DelugeNode
2024-12-03 18:32:48 -03:00
from benchmarks.deluge.tracker import Tracker
class DelugeNodeConfig(BaseModel):
2024-12-06 15:24:11 -03:00
name: str
address: Host
daemon_port: int
listen_ports: list[int] = Field(min_length=2, max_length=2)
class DelugeNodeSetConfig(BaseModel):
2024-12-06 13:52:57 -03:00
network_size: int = Field(gt=1)
2024-12-06 15:24:11 -03:00
name: str
address: str
daemon_port: int
listen_ports: list[int] = Field(min_length=2, max_length=2)
first_node_index: int = 1
nodes: List[DelugeNodeConfig] = []
@model_validator(mode='after')
def expand_nodes(self):
self.nodes = [
DelugeNodeConfig(
2024-12-06 15:24:11 -03:00
name=self.name.format(node_index=str(i)),
2024-11-28 15:52:38 -03:00
address=self.address.format(node_index=str(i)),
daemon_port=self.daemon_port,
listen_ports=self.listen_ports,
)
for i in range(self.first_node_index, self.first_node_index + self.network_size)
]
return self
2024-12-03 18:32:48 -03:00
DelugeDisseminationExperiment = IteratedExperiment[BoundExperiment[StaticDisseminationExperiment[Torrent, DelugeMeta]]]
class DelugeExperimentConfig(ExperimentBuilder[DelugeDisseminationExperiment]):
2024-12-09 16:27:14 -03:00
seeder_sets: int = Field(gt=0, default=1, description='Number of distinct seeder sets to experiment with')
seeders: int = Field(gt=0, description='Number of seeders per seeder set')
repetitions: int = Field(gt=0, description='How many experiment repetitions to run for each seeder set')
file_size: int = Field(gt=0, description='File size, in bytes')
shared_volume_path: Path = Field(description='Path to the volume shared between clients and experiment runner')
tracker_announce_url: HttpUrl = Field(description='URL to the tracker announce endpoint')
nodes: List[DelugeNodeConfig] | DelugeNodeSetConfig = Field(
description='Configuration for the nodes that make up the network')
def build(self) -> DelugeDisseminationExperiment:
2024-12-03 18:32:48 -03:00
nodes_specs = self.nodes.nodes if isinstance(self.nodes, DelugeNodeSetConfig) else self.nodes
network = [
DelugeNode(
2024-12-06 15:24:11 -03:00
name=node_spec.name,
2024-12-03 18:32:48 -03:00
volume=self.shared_volume_path,
daemon_port=node_spec.daemon_port,
daemon_address=str(node_spec.address),
)
for i, node_spec in enumerate(nodes_specs)
]
tracker = Tracker(parse_url(str(self.tracker_announce_url)))
env = ExperimentEnvironment(
components=network + [tracker],
polling_interval=0.5,
)
2024-12-09 16:27:14 -03:00
def repetitions():
for seeder_set in range(self.seeder_sets):
seeders = list(islice(sample(len(network)), self.seeders))
for experiment_run in range(self.repetitions):
yield env.bind(StaticDisseminationExperiment(
network=network,
seeders=seeders,
data=RandomTempData(size=self.file_size,
meta=DelugeMeta(f'dataset-{seeder_set}-{experiment_run}',
2024-12-09 16:27:14 -03:00
announce_url=tracker.announce_url))
))
return IteratedExperiment(repetitions())