Youngjoon Lee 3d14319588
Targeted experiments for queuing mechanism
Targeted experiments for queuing mechanism

gather series into dataframe

put exp_id to the CSV path

revert iterations back to num_nodes/2

add missing print and decrease msg_interval_sec

change param sequence for readability

use struct instead of pickle for fixed-size & faster serde

include dtime series into dataframe

optimize: choose optimized connection type according to latency setting

add skip_sending_noise option

optimize filling up the queue with noises

move queue_type to the end of param set, and build CSV gradually row by row

fix: consider num_senders when waiting until all messages are disseminated

fix: sample senders without duplicate

fix: build param combinations correctly

add plot script

initialize MinSizeMixQueue with noises

define SessionParameterSet and add paramset for session2

improve topology connectivity check to avoid "maxmimum recursions depth exceeded" error

fix: the correct parameter set constructor

store individual series to separate CSV files

reorganize files and draw plot automatically

start series file id from 1 (not 0)

add queue_type CLI argument for parallelization

pretty format of elapsed time

pretty format of elapsed time

add merge CLI and draw multiple plots

split functions

do not draw plot for each session

use concurrent.futures to utilize multiprocessing

add from_paramset argument

fix: count num of finished iterations correctly

draw plots for num_sent_msgs and num_senders for specific experiments
2024-08-02 11:38:17 +09:00

96 lines
2.8 KiB
Python

from __future__ import annotations
import abc
import random
from framework import Framework, Queue
from protocol.temporalmix import PureCoinFlipppingQueue, TemporalMix, TemporalMixConfig
class SimplexConnection(abc.ABC):
"""
An abstract class for a simplex connection that can send and receive data in one direction
"""
@abc.abstractmethod
async def send(self, data: bytes) -> None:
pass
@abc.abstractmethod
async def recv(self) -> bytes:
pass
class LocalSimplexConnection(SimplexConnection):
"""
A simplex connection that doesn't have any network latency.
Data sent through this connection can be immediately received from the other end.
"""
def __init__(self, framework: Framework):
self.queue: Queue[bytes] = framework.queue()
async def send(self, data: bytes) -> None:
await self.queue.put(data)
async def recv(self) -> bytes:
return await self.queue.get()
class DuplexConnection:
"""
A duplex connection in which data can be transmitted and received simultaneously in both directions.
This is to mimic duplex communication in a real network (such as TCP or QUIC).
"""
def __init__(self, inbound: SimplexConnection, outbound: SimplexConnection):
self.inbound = inbound
self.outbound = outbound
async def recv(self) -> bytes:
return await self.inbound.recv()
async def send(self, packet: bytes):
await self.outbound.send(packet)
class MixSimplexConnection(SimplexConnection):
"""
Wraps a SimplexConnection to add a transmission rate and noise to the connection.
"""
def __init__(
self,
framework: Framework,
conn: SimplexConnection,
transmission_rate_per_sec: int,
noise_msg: bytes,
temporal_mix_config: TemporalMixConfig,
# OPTIMIZATION ONLY FOR EXPERIMENTS WITHOUT BANDWIDTH MEASUREMENT
# If True, skip sending a noise even if it's time to send one.
skip_sending_noise: bool,
):
self.framework = framework
self.queue: Queue[bytes] = TemporalMix.queue(
temporal_mix_config, framework, noise_msg
)
self.conn = conn
self.transmission_rate_per_sec = transmission_rate_per_sec
self.noise_msg = noise_msg
self.skip_sending_noise = skip_sending_noise
self.task = framework.spawn(self.__run())
async def __run(self):
while True:
await self.framework.sleep(1 / self.transmission_rate_per_sec)
msg = await self.queue.get()
if self.skip_sending_noise and msg == self.noise_msg:
continue
await self.conn.send(msg)
async def send(self, data: bytes) -> None:
await self.queue.put(data)
async def recv(self) -> bytes:
return await self.conn.recv()