Skip to content

Async Dashboard Approaches

John Gavin edited this page Feb 17, 2026 · 3 revisions

Async Dashboard Approaches

Comprehensive Guide: Understanding the async implementations in randomwalk

Related Pages:


Table of Contents

  1. Overview
  2. Approach 1: Synchronous (workers=0)
  3. Approach 2: Crew-Only Async (Static Snapshots)
  4. Approach 3: Chunked Mode (RECOMMENDED)
  5. Approach 4: Nanonext Broadcasting (DEPRECATED)
  6. Comparison Table
  7. Choosing the Right Approach
  8. Examples

Overview

The randomwalk package provides multiple execution modes for simulation:

Mode workers sync_mode Grid Updates Use Case
Synchronous 0 n/a After each walker WebR/Shinylive, baseline
Static Async 1+ "static" None during sim Production, simplicity
Chunked 1+ "chunked" Between batches RECOMMENDED
Dynamic 1+ "dynamic" ⚠️ DEPRECATED N/A

Approach 1: Synchronous (workers=0)

How It Works

All walkers execute sequentially in the main R process. Each walker sees the grid updated by all previous walkers.

result <- randomwalk::run_simulation(
  grid_size = 100,
  n_walkers = 50,
  workers = 0  # Synchronous mode
)

Key Characteristics

  • WebR/Shinylive compatible: Yes - runs entirely in browser
  • Grid updates: Real-time (each walker sees previous paths)
  • Performance: Sequential, but no overhead
  • Use case: Browser dashboards, baseline comparisons

Approach 2: Crew-Only Async (Static Snapshots)

How It Works

Each worker receives a static copy of the grid at simulation start. Workers execute independently without communication:

Main Process
├─ Create empty grid
├─ Start crew controller
├─ Push walker tasks (each with grid snapshot)
│
│  Worker 1: [Grid copy] → Walker 1 → Walker 3 → Walker 5
│  Worker 2: [Grid copy] → Walker 2 → Walker 4 → Walker 6
│
├─ Wait for all workers
├─ Collect results
├─ Aggregate walker paths onto final grid
└─ Return combined result

Code Example

result <- randomwalk::run_simulation(
  grid_size = 100,
  n_walkers = 50,
  workers = 4,           # Use 4 crew workers
  sync_mode = "static"   # Default: static grid snapshots
)

When Walkers "See" Each Other's Paths

They don't - each walker operates on the initial grid state:

# Walker 1 starts at (50, 50), creates path...
# Walker 2 starts at (30, 30), also uses ORIGINAL grid
# Walker 2 does NOT see Walker 1's path during simulation
# Paths are merged AFTER all walkers complete

Advantages

  • Simple mental model
  • No synchronization overhead
  • Reproducible results
  • Works with any crew backend

Limitations

  • Walkers cannot react to each other's paths
  • Grid state is "stale" during execution
  • Not WebR compatible (crew requires multiple processes)

Approach 3: Chunked Mode (RECOMMENDED)

How It Works

Processes walkers in batches of 10, with grid synchronization between batches:

Batch 1: Walkers 1-10 execute in parallel
         ↓ Grid updated with all new black pixels
Batch 2: Walkers 11-20 execute (see batch 1 results)
         ↓ Grid updated
Batch 3: ...

Code Example

result <- randomwalk::run_simulation(
  grid_size = 100,
  n_walkers = 50,
  workers = 4,
  sync_mode = "chunked"  # RECOMMENDED
)

Advantages

  • ~3x more black pixels than static mode (walkers see previous batches)
  • Better collision detection
  • No socket complexity
  • Good balance of parallelism and interaction

Why Recommended

The chunked mode provides a good balance:

  • Walkers in later batches see earlier batches' paths
  • No complex socket management
  • Works reliably (no deprecated dependencies)

Approach 4: Nanonext Broadcasting (DEPRECATED)

⚠️ DEPRECATED: Both sync_mode = "dynamic" and sync_mode = "mirai_dynamic" are deprecated because nanonext sockets fail in crew/mirai subprocesses. Use "chunked" instead.

What It Was Designed For

Workers would communicate black pixel updates in near real-time using nanonext publish/subscribe sockets.

Why It's Deprecated

# From R/simulation.R:
if (sync_mode %in% c("dynamic", "mirai_dynamic")) {
  logger::log_warn("sync_mode is DEPRECATED: nanonext sockets fail in crew/mirai subprocesses")
  logger::log_warn("Use sync_mode='chunked' for ~3x more black pixels (RECOMMENDED)")
}

Technical reason: nanonext socket handles cannot be passed to crew/mirai subprocess contexts. The sockets become invalid in child processes.

Message Count (For Reference)

When it worked, the message count was:

  • O(N) where N = walkers that create black pixels
  • NOT "10-20 messages" as previously documented
  • Each walker broadcasts at most ONCE (when it terminates adjacent to a black pixel)

Comparison Table

Aspect Sync (workers=0) Static Chunked Dynamic
Status ✅ Active ✅ Active RECOMMENDED ⚠️ DEPRECATED
WebR compatible ✅ Yes ❌ No ❌ No ❌ No
Walker interaction Full None Between batches N/A
Black pixels Baseline Few ~3x more N/A
Overhead None Minimal Minimal N/A
Dependencies None crew crew crew + nanonext

Choosing the Right Approach

Decision Flowchart

Running in WebR/Shinylive?
│
├─ Yes → Use workers=0 (sync) - ONLY option
│
└─ No → Need parallel processing?
         │
         ├─ No → Use workers=0 (sync)
         │
         └─ Yes → Do walkers need to see each other?
                  │
                  ├─ No → Use sync_mode="static"
                  │
                  └─ Yes → Use sync_mode="chunked" (RECOMMENDED)

Quick Reference

Scenario Recommended
Browser dashboard (WebR/Shinylive) workers = 0
Production batch processing workers = 4, sync_mode = "static"
Interactive exploration workers = 4, sync_mode = "chunked"
Maximum walker interaction workers = 0 (sync sees all updates)

Examples

Example 1: WebR/Shinylive Dashboard

# Sync mode - works in browser
result <- randomwalk::run_simulation(
  grid_size = 100,
  n_walkers = 50,
  workers = 0  # Required for WebR
)

Example 2: Production Batch Processing

# Static async - fast, predictable
result <- randomwalk::run_simulation(
  grid_size = 100,
  n_walkers = 100,
  workers = 4,
  sync_mode = "static"
)

Example 3: Interactive Research (RECOMMENDED)

# Chunked mode - best balance
result <- randomwalk::run_simulation(
  grid_size = 200,
  n_walkers = 50,
  workers = 4,
  sync_mode = "chunked"  # Walkers see previous batches
)

See Also


References

Clone this wiki locally