Performance Issues
Diagnosing and fixing slow, laggy, or resource-intensive behavior.
Symptoms
| Issue | Likely Cause | Quick Fix |
|---|---|---|
| Slow scrolling | Large scrollback | Reduce scrollback |
| Input delay | Render bottleneck | Lower render_rate |
| High CPU | Busy loop, bad pattern | Check highlights |
| High memory | Scrollback accumulation | Limit buffer sizes |
| Startup slow | Config parsing | Simplify config |
Performance Configuration
Optimal Settings
[performance]
render_rate = 60 # FPS target (30-120)
batch_updates = true # Combine rapid updates
lazy_render = true # Skip unchanged regions
stream_buffer_size = 50000
# Widget defaults
[defaults.text]
scrollback = 2000 # Lines to keep
auto_scroll = true
Low-Resource Settings
For older systems or constrained environments:
[performance]
render_rate = 30 # Lower FPS
batch_updates = true
lazy_render = true
stream_buffer_size = 20000
[defaults.text]
scrollback = 500 # Minimal scrollback
Scroll Performance
Slow Scrolling
Symptom: Page Up/Down is sluggish, mouse scroll lags
Causes:
- Too much scrollback content
- Complex text styling
- Pattern matching on scroll
Solutions:
-
Reduce scrollback:
[[widgets]] type = "text" scrollback = 1000 # Down from 5000+ -
Simplify highlights:
# Avoid overly complex patterns # Bad - matches everything pattern = ".*" # Better - specific pattern pattern = "\\*\\* .+ \\*\\*" -
Use fast patterns:
[[highlights]] pattern = "stunned" fast_parse = true # Use Aho-Corasick
Scroll Buffer Memory
Symptom: Memory usage grows over time
Solution:
[[widgets]]
type = "text"
scrollback = 2000
scrollback_limit_action = "trim" # Remove old content
Input Latency
Typing Delay
Symptom: Characters appear slowly after typing
Causes:
- Render blocking input
- Network latency
- Pattern processing
Solutions:
-
Priority input processing:
[input] priority = "high" buffer_size = 100 -
Reduce render rate during input:
[performance] input_render_rate = 30 # Lower when typing render_rate = 60 # Normal rate -
Check network:
# Test latency to game server ping -c 10 gs4.play.net
Command Delay
Symptom: Commands take long to send
Solution:
- Check Lich processing time
- Disable unnecessary Lich scripts
- Try direct mode for comparison
CPU Usage
High CPU at Idle
Symptom: CPU high even when nothing happening
Causes:
- Busy render loop
- Bad regex pattern
- Timer spinning
Diagnosis:
# Profile Two-Face
top -p $(pgrep two-face)
# Check per-thread
htop -p $(pgrep two-face)
Solutions:
-
Enable lazy rendering:
[performance] lazy_render = true idle_timeout = 100 # ms before sleep -
Check patterns:
# Avoid catastrophic backtracking # Bad pattern = "(a+)+" # Good pattern = "a+" -
Reduce timers:
[[widgets]] type = "countdown" update_rate = 100 # ms, not too fast
CPU Spikes During Activity
Symptom: CPU spikes during combat/busy scenes
Solutions:
-
Batch updates:
[performance] batch_updates = true batch_threshold = 10 # Combine N updates -
Limit pattern matching:
[[highlights]] pattern = "complex pattern" max_matches_per_line = 10 -
Use simpler widgets:
# Disable complex widgets during heavy activity [widgets.effects] auto_hide = true hide_threshold = 50 # Updates/second
Memory Usage
Memory Growth
Symptom: Memory usage increases continuously
Causes:
- Unlimited scrollback
- Stream buffer growth
- Memory leak (rare)
Solutions:
-
Limit all buffers:
[performance] max_total_memory = "500MB" [[widgets]] type = "text" scrollback = 2000 -
Enable periodic cleanup:
[performance] cleanup_interval = 300 # seconds -
Monitor memory:
watch -n 5 'ps -o rss,vsz -p $(pgrep two-face)'
Large Scrollback
Problem: Each text window can accumulate megabytes
Solution:
# Global limit
[defaults.text]
scrollback = 1000
# Per-widget override only where needed
[[widgets]]
type = "text"
name = "main"
scrollback = 3000 # Main window can be larger
Startup Performance
Slow Launch
Symptom: Takes several seconds to start
Causes:
- Config file parsing
- Font loading
- Network checks
Solutions:
-
Simplify config:
- Split large configs into smaller files
- Remove unused sections
-
Skip network check:
two-face --no-network-check -
Precompile patterns:
[highlights] precompile = true cache_file = "~/.two-face/pattern_cache"
Slow Reconnect
Symptom: Reconnection takes long
Solution:
[connection]
reconnect_delay = 1 # Start at 1 second
reconnect_max_delay = 30 # Cap at 30 seconds
reconnect_backoff = 1.5 # Exponential backoff
Network Performance
High Latency
Symptom: Actions feel delayed
Diagnosis:
# Check network latency
ping gs4.play.net
traceroute gs4.play.net
Solutions:
-
Enable Nagle’s algorithm (if many small packets):
[network] tcp_nodelay = false -
Or disable for lower latency:
[network] tcp_nodelay = true -
Buffer commands:
[input] send_delay = 50 # ms between commands
Bandwidth Issues
Symptom: Connection drops during heavy traffic
Solution:
[network]
receive_buffer = 65536
send_buffer = 32768
Profiling
Built-in Performance Widget
[[widgets]]
type = "performance"
name = "perf"
x = 0
y = 95
width = 100
height = 5
show = ["fps", "memory", "cpu", "network"]
Enable Timing Logs
[logging]
level = "debug"
[debug]
log_render_time = true
log_parse_time = true
log_pattern_time = true
External Profiling
# Linux - perf
perf record -g two-face
perf report
# macOS - Instruments
xcrun xctrace record --template "Time Profiler" --launch two-face
# Cross-platform - flamegraph
cargo flamegraph --bin two-face
Quick Reference
Performance Checklist
- Scrollback limited to reasonable size
- Lazy rendering enabled
- Batch updates enabled
- No catastrophic regex patterns
- Unused widgets disabled
- Network connection stable
- System resources adequate
Key Settings Summary
[performance]
render_rate = 60
batch_updates = true
lazy_render = true
stream_buffer_size = 50000
[defaults.text]
scrollback = 2000
[logging]
level = "warn" # Less logging = more performance
See Also
- Configuration - All settings
- Architecture Performance - Design details
- Common Errors - Error messages