Real Actors - VirtualTimeGenServer

Generated by GenServerVirtualTime โ€ข Mermaid Flowchart

๐Ÿ“ˆ Simulation Summary

Virtual Time
3000ms
Real Time
63ms
Speedup
47.6x
Termination
โฑ Max Time

๐Ÿ“Š Actor Topology

flowchart LR alice("alice
๐Ÿ“ค Sent: 12978
๐Ÿ“ฅ Recv: 12967") bob("bob
๐Ÿ“ค Sent: 13515
๐Ÿ“ฅ Recv: 13504") charlie("charlie
๐Ÿ“ค Sent: 13325
๐Ÿ“ฅ Recv: 13314") diana("diana
๐Ÿ“ค Sent: 13366
๐Ÿ“ฅ Recv: 13356") eve("eve
๐Ÿ“ค Sent: 13107
๐Ÿ“ฅ Recv: 13096") frank("frank
๐Ÿ“ค Sent: 13090
๐Ÿ“ฅ Recv: 13079") grace("grace
๐Ÿ“ค Sent: 13277
๐Ÿ“ฅ Recv: 13266") bob -->|:message| alice diana -->|:message| alice charlie -->|:message| alice bob -->|:message| charlie eve -->|:message| grace charlie -->|:message| grace eve -->|:message| charlie frank -->|:message| bob charlie -->|:message| frank bob -->|:message| diana grace -->|:message| frank grace -->|:message| eve diana -->|:message| eve grace -->|:message| diana grace -->|:message| bob diana -->|:message| grace alice -->|:message| eve grace -->|:message| alice charlie -->|:message| diana eve -->|:message| bob eve -->|:message| diana eve -->|:message| frank alice -->|:message| charlie bob -->|:message| grace frank -->|:message| eve alice -->|:message| diana alice -->|:message| grace charlie -->|:message| eve bob -->|:message| frank diana -->|:message| charlie charlie -->|:message| bob frank -->|:message| alice eve -->|:message| alice frank -->|:message| diana alice -->|:message| bob frank -->|:message| grace diana -->|:message| frank frank -->|:message| charlie diana -->|:message| bob grace -->|:message| charlie alice -->|:message| frank bob -->|:message| eve style alice fill:#fff3e0,stroke:#f57c00,stroke-width:3px style bob fill:#fff3e0,stroke:#f57c00,stroke-width:3px style charlie fill:#fff3e0,stroke:#f57c00,stroke-width:3px style diana fill:#fff3e0,stroke:#f57c00,stroke-width:3px style eve fill:#fff3e0,stroke:#f57c00,stroke-width:3px style frank fill:#fff3e0,stroke:#f57c00,stroke-width:3px style grace fill:#fff3e0,stroke:#f57c00,stroke-width:3px

Node Shapes (Actor Type)

flowchart TD legend_processor("Processor
(send & receive)") style legend_processor fill:#ffffff,stroke:#666666,stroke-width:2px

Node Colors (Activity Level)

flowchart LR activity_0["๐ŸŸ  High Activity (>50 msgs)"] style activity_0 fill:#fff3e0,stroke:#f57c00,stroke-width:3px

๐Ÿ“‰ Detailed Statistics

Actor Sent Received Send Rate Receive Rate Activity
alice 12978 12967 4326.0 msg/s 4322.33 msg/s 25945 total
bob 13515 13504 4505.0 msg/s 4501.33 msg/s 27019 total
charlie 13325 13314 4441.67 msg/s 4438.0 msg/s 26639 total
diana 13366 13356 4455.33 msg/s 4452.0 msg/s 26722 total
eve 13107 13096 4369.0 msg/s 4365.33 msg/s 26203 total
frank 13090 13079 4363.33 msg/s 4359.67 msg/s 26169 total
grace 13277 13266 4425.67 msg/s 4422.0 msg/s 26543 total
Summary: Total messages: 185240 โ€ข Duration: 3000ms โ€ข Actors: 7

๐Ÿ’ป Model Source Code

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)