| Actor | Sent | Received | Send Rate | Receive Rate | Activity |
|---|---|---|---|---|---|
| alice | 14497 | 14485 | 4832.33 msg/s | 4828.33 msg/s | 28982 total |
| bob | 14767 | 14755 | 4922.33 msg/s | 4918.33 msg/s | 29522 total |
| charlie | 14916 | 14905 | 4972.0 msg/s | 4968.33 msg/s | 29821 total |
| diana | 14715 | 14704 | 4905.0 msg/s | 4901.33 msg/s | 29419 total |
| eve | 14549 | 14538 | 4849.67 msg/s | 4846.0 msg/s | 29087 total |
| frank | 14465 | 14454 | 4821.67 msg/s | 4818.0 msg/s | 28919 total |
| grace | 14792 | 14781 | 4930.67 msg/s | 4927.0 msg/s | 29573 total |
This is the Elixir code that defines the actor simulation model:
# Create 7 real GenServer actors that randomly send :hi messages
# Using VirtualTimeGenServer for virtual time support
defmodule HiActor do
use VirtualTimeGenServer
def start_link(name, targets, all_actors) do
initial_state = %{
name: name,
targets: targets,
all_actors: all_actors,
sent_count: 0,
received_count: 0
}
VirtualTimeGenServer.start_link(__MODULE__, initial_state, name: name)
end
def handle_info(:send_random_message, state) do
# Choose random target and send :hi
target = Enum.random(state.targets)
VirtualTimeGenServer.cast(target, {:hi, state.name})
# Schedule next message with random delay 200-300ms
delay = :rand.uniform(101) + 200
VirtualTimeGenServer.send_after(self(), :send_random_message, delay)
{:noreply, %{state | sent_count: state.sent_count + 1}}
end
def handle_cast({:hi, from}, state) do
# Simulate processing time for handling the message (50-150ms)
processing_delay = :rand.uniform(101) + 50
VirtualTimeGenServer.sleep(processing_delay)
# Received :hi, send random response
available_targets = Enum.reject(state.all_actors, &(&1 == from))
if length(available_targets) > 0 do
target = Enum.random(available_targets)
VirtualTimeGenServer.cast(target, {:hi, state.name})
end
{:noreply, %{state | received_count: state.received_count + 1}}
end
end
# Create simulation with real actors
all_actors = [:alice, :bob, :charlie, :diana, :eve, :frank, :grace]
simulation =
ActorSimulation.new(trace: true)
|> ActorSimulation.add_process(:alice,
module: HiActor,
args: [:alice, [:bob, :charlie, :diana, :eve, :frank, :grace], all_actors])
|> ActorSimulation.add_process(:bob,
module: HiActor,
args: [:bob, [:alice, :charlie, :diana, :eve, :frank, :grace], all_actors])
|> ActorSimulation.add_process(:charlie,
module: HiActor,
args: [:charlie, [:alice, :bob, :diana, :eve, :frank, :grace], all_actors])
|> ActorSimulation.add_process(:diana,
module: HiActor,
args: [:diana, [:alice, :bob, :charlie, :eve, :frank, :grace], all_actors])
|> ActorSimulation.add_process(:eve,
module: HiActor,
args: [:eve, [:alice, :bob, :charlie, :diana, :frank, :grace], all_actors])
|> ActorSimulation.add_process(:frank,
module: HiActor,
args: [:frank, [:alice, :bob, :charlie, :diana, :eve, :grace], all_actors])
|> ActorSimulation.add_process(:grace,
module: HiActor,
args: [:grace, [:alice, :bob, :charlie, :diana, :eve, :frank], all_actors])
|> ActorSimulation.run(duration: 3000)