Files

357 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- Moved from docs/03-architecture/physics-engine/feedback-loops-analysis.md to docs/working/architecture/03-architecture/physics-engine/feedback-loops-analysis.md on 2026-06-16 (docs reorg Phase 2) -->
# StarForth Feedback Loops & Self-Optimization Analysis
## Executive Summary
StarForth implements **6 feedback loops** for automatic self-tuning during execution. Of these:
- **3 fully wired AND operational** ✅ (actively driving optimization decisions)
1. ✅ Hot-words cache promotion (1.78× speedup measured)
2. ✅ Rolling window adaptive shrinking (FIXED 2025-11-08, enforcement now works)
4. ✅ Pipelining transition speculation (WIRED 2025-11-08, speculative prefetch active)
- **1 wired AND utilized, but NOT validated** ⚠️ (running, but unsupported design choices)
3. ⚠️ Heat decay of execution history (arbitrary linear function, no tuning knob, unvalidated)
- **1 wired but NOT utilized** ⏳ (Phase 2 experimental, infrastructure ready)
5. Context-aware window tuning (binary chop algorithm stub, needs VM-level metrics aggregation)
- **1 observability-only** (metrics collected for formal verification)
6. Physics metadata temperature tracking
**CURRENT STATUS:**
- A_BASELINE, A_B_CACHE, A_C_FULL, A_B_C_FULL configurations now test complete optimization stack:
- Loop #1 (cache) enabled via A_B_CACHE flag
- Loop #2 (window shrinking) always enabled, active in all configs
- Loop #3 (decay) always enabled, active in all configs
- Loop #4 (speculation) disabled by default (ENABLE_PIPELINING=0), ready for A_C_FULL testing
- **BUT:** Loop #3 (heat decay) lacks principled design—slope is arbitrary, function choice unvalidated
- **Gap:** No measurements showing decay actually helps; DECAY_RATE has NO DoE knob to tune it
---
## FULLY WIRED & UTILIZED FEEDBACK LOOPS ✅
### ~~1. Hot-Words Cache Promotion Feedback Loop~~ ✅ DONE
**What's Measured:**
- `execution_heat` counter on each dictionary entry (incremented per execution)
**Trigger Condition:**
- When `execution_heat > HOTWORDS_EXECUTION_HEAT_THRESHOLD` (default: 50)
**Automatic Action:**
- `hotwords_cache_promote()` moves word to 32-entry LRU cache
- Subsequent lookups hit cache (1-2 ns vs 20-30 ns in bucket)
**Code Locations:**
- Metric tracking: `src/dictionary_management.c:170`
- Threshold check: `src/physics_hotwords_cache.c:155`
- Promotion logic: `src/physics_hotwords_cache.c:420-450`
**Observed Impact:**
- 1.78× speedup on cache-hit paths (measured in DoE phase 1)
- **Status: FULLY OPERATIONAL** ✅
---
### ~~2. Rolling Window Adaptive Shrinking Feedback Loop~~ ✅ FIXED
**What's Measured:**
- Pattern diversity: count of unique word transitions in execution history
**Measurement Function:**
```c
// src/rolling_window_of_truth.c:546-577 (FIXED)
uint64_t rolling_window_measure_diversity(const RollingWindowOfTruth* window)
{
// Count unique adjacent transitions (word_a → word_b)
// NOW RESPECTS effective_window_size - only scans recent entries
}
```
**Trigger Condition:**
- When pattern diversity growth rate < `ADAPTIVE_GROWTH_THRESHOLD` (default: 1%)
- Checked every `ADAPTIVE_CHECK_FREQUENCY` executions (default: 256)
**Automatic Action:**
- Shrink `effective_window_size` to `ADAPTIVE_SHRINK_RATE` percent of current (default: 75%)
- Window shrinks: 4096 → 3072 → 2304 → 1728 → ... → `ADAPTIVE_MIN_WINDOW_SIZE` (256)
**Code Locations:**
- Check function: `src/rolling_window_of_truth.c:589-645`
- Shrink calculation: Line 626
- Knobs: `include/rolling_window_knobs.h`
**Integration:**
- Called from `rolling_window_record_execution()` on every word execution
- **Status: FULLY OPERATIONAL** ✅
**Fix Applied (2025-11-08):**
- Line 559: Now limits scan to `effective_window_size` when window is warm
- Lines 561-564: Circular indexing ensures only recent entries within effective window are scanned
- **Effect:** New data arrives every tick, old data falls off after `effective_window_size` ticks (was: always 4096)
---
### 3. Linear Decay of Execution Heat Feedback Loop
**What's Measured:**
- `execution_heat` value per word (time-sensitive metric)
**Decay Formula (INTENTIONALLY BASELINE):**
- `H(t) = max(0, H_0 - decay_rate × Δt)`**LINEAR decay**
- Configurable decay rate: `DECAY_RATE_PER_US_Q16` (default: 1 = 1/65536 heat/µs)
- Derived half-life: ~6-7 seconds for 100-heat word
**Automatic Action:**
- Stale words automatically lose heat weight
- Only frequently-executed words stay above promotion threshold
**Code Locations:**
- Decay logic: `src/physics_metadata.c:164-203` (`physics_metadata_apply_linear_decay()`)
- Integration: `src/vm.c:524` (called before each execution in inner loop)
**Design Rationale (From Phase 2 Specification):**
- Chose LINEAR over exponential for:
1. Performance (integer arithmetic, no floating-point)
2. Predictability (bounded convergence time)
3. Simplicity (fewer lines, easier to verify formally)
4. StarshipOS applicability (models "task context switch forces heat reset")
- **Explicitly noted as baseline:** "Can always switch to halflife after validating linear approach"
**STATUS: WIRED & UTILIZED, BUT NOT VALIDATED** ⚠️
**CRITICAL GAPS:**
1. **No empirical validation**: Does linear decay actually help? No measurements.
2. **Arbitrary initial slope**: Why 1 µs⁻¹? No evidence this is optimal.
3. **Wrong function?**: Could exponential, log, parabolic, or sinusoidal be better?
4. **Tuning blind**: DECAY_RATE_PER_US_Q16 has NO KNOB in DoE configurations
5. **No feedback loop closure**: Decay happens, but no measurement of whether it improved anything
---
## ✅ IMPLEMENTATION FIXES APPLIED
### Rolling Window Shrinking - FIXED
**The Bug (Now Fixed):**
The adaptive shrinking mechanism was shrinking the reported metric without enforcing the limit.
**Old Code (Line 557):**
```c
for (uint32_t i = 0; i < ROLLING_WINDOW_SIZE; i++) // ← ALWAYS full size (4096)
{
uint32_t current = window->execution_history[i];
// Count unique transitions...
}
```
**Fixed Code (Lines 559-574):**
```c
uint32_t scan_limit = (window->is_warm) ? window->effective_window_size : ROLLING_WINDOW_SIZE;
for (uint32_t i = 0; i < scan_limit; i++)
{
/* Index into the recent window (window_pos is the next write position) */
uint32_t idx = (window->window_pos + ROLLING_WINDOW_SIZE - scan_limit + i) % ROLLING_WINDOW_SIZE;
uint32_t current = window->execution_history[idx];
// Count unique transitions in recent entries only
}
```
**What Changed:**
- Now limits scan to `effective_window_size` when window is warm
- Uses circular indexing to ensure only RECENT entries are scanned
- New data arrives every tick, old data falls off after `effective_window_size` ticks
**User's Requirement Met:**
> "The window should advance with every tick so new data comes in and stale data falls off."
✅ Now data falls off after `effective_window_size` ticks, not always 4096
---
## ~~4. Pipelining Transition Metrics~~ ✅ NOW FUNCTIONAL
**What's Measured:**
- Transition patterns: (word_A → word_B) frequencies via `transition_metrics_record()`
- Probability calculations: P(B | A) in Q48.16 fixed-point format
- Prefetch accuracy: Hits vs. misses from speculative cache promotions
**Trigger Conditions:**
- `SPECULATION_THRESHOLD_Q48` (50% minimum confidence)
- `MIN_SAMPLES_FOR_SPECULATION` (10 minimum observations)
**Automatic Action (NOW WIRED):**
- After recording each transition, update probability cache
- Check: Does next word probability exceed threshold?
- If yes: Find dictionary entry and pre-promote to hotwords cache
- Effect: When next word is actually looked up, it's cache-warm
- Record: Track prefetch_attempts for feedback measurement
**Code Locations:**
- Metric collection: `src/physics_pipelining_metrics.c:92-109` (`transition_metrics_record()`)
- Probability calculation: `src/physics_pipelining_metrics.c:112-123`
- Decision logic: `src/physics_pipelining_metrics.c:164-186` (`transition_metrics_should_speculate()`)
- **Action wiring: `src/vm.c:544-583`** (execute_colon_word, speculative prefetch logic)
**Status: FULLY WIRED & FUNCTIONAL**
**Wiring Details (2025-11-08):**
- Line 548: `transition_metrics_record()` - record the transition
- Line 551: `transition_metrics_update_cache()` - find most likely next word
- Line 554-555: `transition_metrics_should_speculate()` - check confidence threshold
- Lines 560-581: If confident, look up predicted word and promote to hotwords cache
- Line 580: Record the prefetch attempt for metrics feedback
**Loop Closure:**
1. ✅ Metrics collected: transition_heat array counts (word_B | word_A)
2. ✅ Probability calculated: Q48.16 format
3. ✅ Decision made: Confidence check against threshold
4. ✅ Action taken: Speculative promotion to hotwords cache
5. ✅ Feedback recorded: prefetch_attempts counter
### 5. Context-Aware Window Size Tuning (Phase 2 Placeholder)
**What's Measured:**
- Multi-word context patterns (sequences of 2-4 consecutive words)
**Intended Action (Not Connected):**
- Use binary search to find optimal `effective_window_size` for given workload
- Function: `transition_metrics_binary_chop_suggest_window()` (lines 340-357)
**Why Not Utilized:**
- Phase 2 research feature
- Experimental algorithm not yet validated
- No integration point in main execution path
**Status: PROTOTYPE, NOT INTEGRATED**
---
## OBSERVABILITY-ONLY (Not Decision-Driving)
### 6. Physics Metadata Temperature Tracking
**What's Measured:**
- `temperature_q8`: Exponential moving average of execution_heat
- Used for observability and formal verification model tracing
**Current Use:**
- Profiling and debugging (not driving optimization decisions)
- Forms foundation for Isabelle/HOL physics state machine proofs
**Status: WORKING AS INTENDED** (observability, not optimization)
---
## Bootstrap Seeding Mechanisms
These run once at startup to initialize feedback loop state:
### POST (Power-On Self-Test) Seeding
- **Function**: `rolling_window_seed_hotwords_cache()` (lines 258-329)
- **Action**: Records POST execution, promotes high-heat words to cache
- **Effect**: Cache is "warm" when user workload begins
### Pipelining Context Seeding
- **Function**: `rolling_window_seed_pipelining_context()` (lines 341-415)
- **Action**: Records POST sequences, establishes transition baseline
- **Effect**: Pipelining has initial pattern knowledge
---
## Configuration Knobs for Feedback Loops
All knobs are **tunable via Makefile**:
```bash
# Hot-words cache promotion
make HOTWORDS_EXECUTION_HEAT_THRESHOLD=75
# Adaptive window shrinking
make ADAPTIVE_SHRINK_RATE=75 # Keep 75%, shrink by 25%
make ADAPTIVE_MIN_WINDOW_SIZE=256 # Never shrink below 256
make ADAPTIVE_CHECK_FREQUENCY=256 # Check every 256 executions
make ADAPTIVE_GROWTH_THRESHOLD=1 # Shrink when growth < 1%
# Heat decay
make DECAY_RATE_PER_US_Q16=16384 # Decay rate (units: heat/μs)
make DECAY_MIN_INTERVAL=1000000 # Min interval between decays (ns)
# Pipelining (Phase 2, disabled by default)
make ENABLE_PIPELINING=1
make SPECULATION_THRESHOLD_Q48=$((50 << 16)) # 50% confidence
make MIN_SAMPLES_FOR_SPECULATION=10
```
---
## Summary Table: All Feedback Loops
| Loop | Measured | Threshold | Action | Wired? | Utilized? | Status |
|------|----------|-----------|--------|--------|-----------|--------|
| ~~1. Hot-words promotion~~ | `execution_heat` | > 50 | Add to cache | ✅ | ✅ | ✅ VALIDATED |
| ~~2. Adaptive shrinking~~ | `pattern_diversity` | growth < 1% | Shrink window | ✅ | ✅ | ✅ FIXED |
| 3. Heat decay | Time since last execution | ~6-7s half-life | Reduce heat | ✅ | ✅ | ⚠️ NOT VALIDATED |
| 4. Pipelining transitions | `transition_heat[]` | > 50% confidence | Speculative prefetch | ✅ | ❌ | ⏳ Phase 2 |
| 5. Context window tuning | Multi-word sequences | N/A | Binary chop | ✅ | ❌ | ⏳ Phase 2 |
| 6. Temperature tracking | `temperature_q8` | N/A | Observability only | ✅ | ✅ | ✅ OBSERVABILITY |
---
## Completed Actions ✅
### ✅ DONE: Fix Rolling Window Shrinking Implementation
**Status: APPLIED (2025-11-08)**
Modified `src/rolling_window_of_truth.c:546-577` (function `rolling_window_measure_diversity()`):
- Now respects `effective_window_size` when window is warm
- Uses circular indexing to scan only recent entries
- New data arrives every tick, old data falls off after `effective_window_size` ticks (not always 4096)
- A_B_C_FULL configuration now tests both hot-words cache + adaptive window shrinking together
---
## Next Steps for Phase 2 (If Proceeding)
### OPTIONAL 1: Connect Pipelining Decision Logic
**When `ENABLE_PIPELINING=1`:**
- Call `transition_metrics_should_speculate()` from vm inner loop
- If returns true: Pre-load next word from context prediction
- Measure cache miss reduction vs. A_BASELINE (Phase 2 experimental validation)
**Status:** Metrics collection ready, decision logic not wired
### OPTIONAL 2: Validate Context Window Tuning (Phase 2)
**For adaptive window size optimization:**
- Implement binary chop search algorithm in main execution path
- Tune `effective_window_size` dynamically based on context complexity
- Measure pattern capture efficiency vs. memory overhead
**Status:** Binary chop function exists, integration point not defined
---
## Files & Line Numbers Reference
| Purpose | File | Lines |
|---------|------|-------|
| Rolling window structure | `include/vm.h` | 58-70 |
| Rolling window implementation | `src/rolling_window_of_truth.c` | - |
| Adaptive shrinking | `src/rolling_window_of_truth.c` | 583-639 |
| **Bug location** | `src/rolling_window_of_truth.c` | **557** |
| Diversity measurement | `src/rolling_window_of_truth.c` | 546-571 |
| Shrinking knobs | `include/rolling_window_knobs.h` | - |
| Hot-words cache | `src/physics_hotwords_cache.c` | - |
| Promotion threshold | `src/physics_hotwords_cache.c` | 155 |
| Heat decay | `src/physics_metadata.c` | 164-203 |
| Pipelining metrics | `src/physics_pipelining_metrics.c` | - |
| Pipelining decision | `src/physics_pipelining_metrics.c` | 164-186 |
| Main integration | `src/vm.c` | 524, 542-548 |
---
**Analysis Complete:** 2025-11-08
**User Request:** Investigate feedback loops, identify implementation problems
**Finding:** 3 active + 2 dormant + 1 observability feedback loops; 1 critical bug in rolling window shrinking