Files
LithosAnanake/docs/working/architecture/03-architecture/heartbeat-system/critical-insight.md
T

8.4 KiB

CRITICAL INSIGHT: Heartbeat Rate is Variable, Not Fixed

Date: November 20, 2025 Status: Game-changer for Phase 2 DoE Impact: Previous design was incomplete


The Discovery

The heartbeat isn't a fixed 1ms tick. It's a variable rate that adapts to system load:

/* In HeartbeatWorker struct (vm.c:64) */
uint64_t tick_ns;  /* ← THIS VARIES! Not constant! */

/* In heartbeat_thread_main() (vm.c:695) */
uint64_t tick_ns = worker->tick_ns ? worker->tick_ns : HEARTBEAT_TICK_NS;

What this means:

  • Default: ~1,000,000 ns (1 kHz)
  • Can be adjusted by inference engine to respond to load
  • Different configurations may modulate heartbeat differently
  • This is THE physics feedback mechanism we should measure!

Why This Matters for Phase 2

Previous Design (INCOMPLETE)

Baseline (Stage 1): HEARTBEAT_THREAD_ENABLED=0
├─ Fixed 1ms tick (no modulation)
├─ No adaptive behavior
└─ Result: "System is deterministic, stable"
   ↳ WRONG! We disabled the feature that makes it adaptive!

Correct Design (This Changes Everything)

Phase 2: HEARTBEAT_THREAD_ENABLED=1 (WITH modulation)
├─ Heartbeat rate VARIES per tick (tick_ns changes)
├─ Inference engine adjusts tick_ns based on workload
├─ Different configs modulate heartrate differently
└─ Result: Measure which config has BEST load responsiveness
   ↳ Golden config = smoothest, most responsive heartrate modulation

The Physics Story (What's Really Happening)

Load Increases → System Slows Heartbeat (Thinking Time)

High workload detected
  ↓
Inference engine: "System is busy, I need more thinking time"
  ↓
Increases tick_ns (slows heartbeat, e.g., 1ms → 2ms)
  ↓
Heartbeat runs less frequently (gives inference more CPU time)
  ↓
Physics parameters converge faster
  ↓
System adapts and performance improves

Expected Behavior of Good Configs

  • Responsive: tick_ns increases under load (slower heartbeat = more tuning time)
  • Smooth: No wild oscillation in tick_ns values
  • Efficient: Results in better overall performance

Expected Behavior of Bad Configs

  • Unresponsive: tick_ns stays fixed (doesn't adapt to load)
  • Oscillating: tick_ns bounces around wildly
  • Inefficient: Heartrate adaptation makes things worse, not better

What Stage 1 Missed

Stage 1 baseline ran without heartbeat thread:

HEARTBEAT_THREAD_ENABLED=0  /* Thread disabled */

This means:

  • ✗ No tick_ns modulation
  • ✗ No adaptive behavior
  • ✗ System can't respond to load
  • ✗ Physics isn't actually running

Stage 1 conclusion was incomplete: "These 5 configs are good" — but we don't know if their heartrate MODULATION is good!


What Phase 2 Should Actually Measure

Primary Metric: Heartbeat Rate Modulation Quality

Not "jitter in a fixed tick", but "how well does heartrate respond to load?"

Measure these per run:

  1. Heartbeat Rate Trajectory

    tick_ns values: [1000000, 1200000, 1400000, 1200000, 1100000, 1050000, ...]
    Convert to Hz:  [1000,    833.3,   714.3,   833.3,   909.1,   952.4,   ...]
    
  2. Load-Heartrate Correlation

    For each tick:
      workload = lookups_this_tick
      heartrate_hz = 1e9 / tick_ns
    
    Correlation(workload, heartrate_hz) = ?
    - Positive: heartrate DECREASES under load (slower, more thinking time) ✓ GOOD
    - Negative: heartrate INCREASES under load (faster, less tuning)  ✗ BAD
    - Zero: heartrate doesn't respond to load                        ✗ NO ADAPTATION
    
  3. Heartrate Stability

    - Does heartrate converge to a steady state?
    - How smooth is the convergence?
    - Does it oscillate?
    - How long to settle?
    
  4. Performance Impact

    - Does heartrate modulation improve execution time?
    - Is the system faster with adaptive heartrate?
    

Golden Configuration Characteristics

The winner should have:

Responsive heartrate (tick_ns changes with load) ✓ Negative correlation (slower heartbeat under heavy load = more thinking time) ✓ Smooth modulation (no wild oscillations) ✓ Fast convergence (settles within ~1000 ticks) ✓ Performance improvement (adaptive heartrate makes system faster/better)

If a config has none of these, it's not adaptive — it's just a static heartbeat.


The Missing Code (What Needs to Happen)

Current State

/* heartbeat_thread_main() in vm.c:682 */
static void* heartbeat_thread_main(void *arg) {
    /* ... runs heartbeat cycle ... */

    uint64_t tick_ns = worker->tick_ns ? worker->tick_ns : HEARTBEAT_TICK_NS;

    /* Sleep for tick_ns nanoseconds */
    nanosleep(&req, &rem);

    /* ← tick_ns value is lost! We don't capture it! */
}

We need to LOG tick_ns per tick!

What's Missing

/* NEEDED: Capture tick_ns trajectory */
struct HeartbeatRateSample {
    uint64_t tick_number;
    uint64_t tick_ns;        /* ← THE HEARTBEAT RATE */
    uint64_t workload_ops;   /* Dictionary lookups this tick */
    uint64_t timestamp_ns;
};

/* In heartbeat_thread_main(), capture sample before sleep */
capture_heartbeat_rate_sample(vm, tick_ns, workload_ops_this_tick);

/* Store samples in rolling buffer in VM struct */

Then Analyze

# Load tick_ns trajectory
heartrate_samples <- read.csv("heartbeat_rates_config_1_run_1.csv")

# Compute metrics
heartrate_hz <- 1e9 / heartrate_samples$tick_ns
load_per_tick <- heartrate_samples$workload_ops

# Measure correlation
correlation <- cor(load_per_tick, heartrate_hz)
# ← This tells us: does heartrate respond to load?

# Expected for good config: correlation > 0.7 (strong negative)
# ← Negative = slower heartrate under heavy load ✓

Revised Experimental Question

Old (Incomplete): "Which config is most stable?" → Measured: interval jitter in fixed 1ms tick

New (Correct): "Which config has the best heartbeat rate modulation?" → Measure: tick_ns trajectory, load-response coupling, convergence smoothness


Why This is Important

The heartbeat rate modulation is the core physics mechanism:

Without adaptive heartbeat:
├─ System can't respond to load changes
├─ Physics parameters don't converge
├─ Performance stagnates
└─ "Stability" is just having a steady bad system

With adaptive heartbeat (Phase 2):
├─ System modulates heartbeat in response to load
├─ Physics gets thinking time when needed
├─ Parameters converge dynamically
├─ "Stability" means smooth, responsive adaptation
└─ Performance improves over time

The golden config isn't the one with the steadiest heartbeat — it's the one with the BEST ADAPTIVE response.


Implementation Priority

HIGH PRIORITY (Blocking)

  1. Extend HeartbeatWorker: Add tick_ns sample logging
  2. Modify heartbeat_thread_main(): Capture tick_ns trajectory
  3. Update DoeMetrics: Add heartrate modulation metrics
  4. Update CSV schema: Include heartrate trajectory data

MEDIUM PRIORITY (Affects analysis)

  1. Modify R analysis to focus on load-heartrate coupling
  2. Update golden config selection criteria
  3. Generate heartrate response plots

LOW PRIORITY (Nice-to-have)

  1. Visualize tick_ns trajectory over time
  2. Compare heartrate modulation patterns across configs

Expected Results (When Done Right)

Config Analysis

Config Heartrate Responsiveness Load Coupling Convergence Expected Rank
1_0_1_1_1_0 High (modulates 1→2ms) 0.82 Fast 🥇 Gold
1_0_1_1_1_1 High 0.78 Medium 🥈 Silver
1_1_0_1_1_1 Medium 0.65 Slow 🥉 Bronze
1_0_1_0_1_0 Low (sluggish) 0.55 Very slow 4th
0_1_1_0_1_1 None (fixed) 0.20 N/A 5th

The golden config will be the one with highest load-heartrate correlation.


Summary

You were right: We need to measure heartbeat rate, not just "jitter in a fixed tick".

The heartbeat is adaptive, and the quality of that adaptation is what differentiates the configurations.

Next: Implement heartrate trajectory logging and re-run the Phase 2 DoE focused on load responsiveness.

This is the real physics story. ✓