ZSHAND Profile Report Guide¶
Overview¶
The ZSHAND Profile Report is a comprehensive performance analysis tool that transforms raw timing data into an actionable performance dashboard. It helps you understand where your shell startup time is spent and provides intelligent recommendations for optimization.
Table of Contents¶
- Generating a Profile Report
- Understanding the Report
- Performance Grading
- Configuring Exceptions
- Interpreting Recommendations
- Troubleshooting
Generating a Profile Report¶
Prerequisites¶
You must first run a profile session to collect timing data:
# Option 1: Profile current session (collects data on next shell start)
zprofile
# Option 2: Run full profiling bundle
zfull
Running the Report¶
Once profiling data is available, generate the report:
# Generate report (reads from default cache location)
zsh build/profile_bundle_report.zsh
# Or specify custom cache directory
zsh build/profile_bundle_report.zsh ~/.cache/zshand
The report will display:
- Executive performance summary
- Visual load timeline
- Smart insights with traffic light indicators
- Detailed breakdowns by component
- Actionable optimization opportunities
Understanding the Report¶
The report is organized into several sections, presented in order of importance:
1. Executive Summary 🚀¶
╔══════════════════════════════════════════════════════════════════════╗
║ 🚀 STARTUP PERFORMANCE SUMMARY ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ Total Startup Time: 154.2ms Grade: C ⭐⭐ ║
║ Async Operations: 221.6ms (deferred) ║
║ ║
║ Performance: ░░░░░░░░░░░░░░░░░░ 1 ACCEPTABLE ║
║ ║
║ Bottleneck: Directory: core (71.1ms, 46.1) ║
║ Opportunity: Consider lazy loading 10-you-should-use plugin ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
What it shows:
- Total Startup Time: Actual blocking time before prompt appears
- Grade: A-F rating (see Performance Grading)
- Async Operations: Time saved by deferred/lazy loading
- Performance Bar: Visual representation (relative to 100ms ideal)
- Bottleneck: The slowest component identified
- Opportunity: Primary optimization recommendation
2. Load Timeline ⏱️¶
║ 0ms ├─────────────────────────────────────────────────────┤ 154.2ms ║
║ │ │ ║
║ ├─ Core (71.1ms) ▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░ 46% ║
║ ├─ Plugins (30.4ms) ██████░░░░░░░░░░░░░░░░░░░░░░░░ 20% ║
Visual timeline showing:
- Proportional bars for each major component
- Percentage of total time
- Async operations listed separately ("AFTER PROMPT")
3. Smart Insights 💡¶
║ 🟢 Core system: Good (71.1ms) ║
║ Good - typical for feature-rich frameworks ║
║ ║
║ 🟡 Plugin ecosystem: Acceptable (30.4ms) ║
║ 10-you-should-use takes 16.3ms - consider lazy loading ║
Indicators:
- 🟢 Green: Excellent performance, no action needed
- 🟡 Yellow: Acceptable but could be optimized
- 🔴 Red: Slow, optimization recommended
Context-aware messages explain:
- Whether performance is normal for the component type
- Comparisons to typical setups
- Time savings from current optimizations
4. Section Deep Dive¶
Detailed breakdowns for major sections (Core, Plugins, Hooks):
╭──────────────────────────────────────────────────────────────────────╮
│ 🔌 PLUGINS 30.4ms 19.7% of total │
├──────────────────────────────────────────────────────────────────────┤
│ 1. 10-you-should-use.zsh 16.3ms ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░ 54% / 11% │
│ 2. 99-zsh-syntax-highlighting.zsh 4.9ms ▓▓▓░░░░░░░░░░░░░░░░░ 16% / 3% │
│ │
│ Analysis: Acceptable - consider lazy loading heavy plugins │
│ Action: Plugins are well-optimized │
╰──────────────────────────────────────────────────────────────────────╯
For each section:
- Shows top 5-8 slowest files
- Two percentages:
% of section/% of total - Visual bar scaled to slowest in section
- Analysis and recommended action
5. Optimization Opportunities 🎯¶
║ Priority 1: HIGH IMPACT 💰💰💰 ║
║ ──────────────────────────────────────────────────────────────── ║
║ • Lazy load 10-you-should-use plugin ║
║ Current: 16.3ms blocking Potential: ~14ms saved ║
║ How: Move to deferred loading or lazy widget ║
Priority levels:
- HIGH IMPACT 💰💰💰: Save >10ms
- MEDIUM IMPACT 💰💰: Save 5-10ms
- LOW IMPACT 💰: Save <5ms
WINS section shows what's already optimized:
║ 🌟 WINS: You're already doing these right! ║
║ ──────────────────────────────────────────────────────────────── ║
║ ✓ Deferred operations save ~226.0ms from startup ║
║ ✓ 42 widgets use lazy loading (saves ~50-100ms) ║
Performance Grading¶
The report assigns an overall grade based on total startup time:
| Grade | Time Range | Stars | Meaning |
|---|---|---|---|
| A | < 50ms | 🌟🌟🌟🌟 | Excellent - lightning fast |
| B | 50-150ms | ⭐⭐⭐ | Good - smooth experience |
| C | 150-250ms | ⭐⭐ | Acceptable - room for improvement |
| D | 250-500ms | ⭐ | Slow - optimization needed |
| F | > 500ms | 🐌 | Very slow - significant issues |
Note: Async operations (deferred/lazy) don't count against your grade since they run after the prompt appears.
Configuring Exceptions¶
Sometimes a slow operation is acceptable because its value outweighs the cost. Use the exceptions configuration to suppress recommendations for these cases.
Exception File Location¶
config/profile-exceptions.conf
Format¶
- pattern: Glob pattern matching filename (e.g.,
*.zsh,exact-name.zsh) - max_time_ms: Maximum acceptable time in milliseconds
- reason: Documentation for why this is acceptable
Examples¶
# Allow you-should-use plugin up to 20ms
10-you-should-use.zsh|20|Command suggestions feature is worth the cost
# Allow any syntax highlighting plugin up to 10ms
*-syntax-highlighting.zsh|10|Syntax highlighting requires processing
# Allow atuin history search up to 15ms
02_atuin.zsh|15|Advanced history search integration justified
How It Works¶
- Report loads exceptions during startup
- When identifying slow operations, checks if they match exception patterns
- If time is within exception threshold, operation is filtered from recommendations
- Report shows "📝 NOTE: Exceptions Applied" with count
When to Use Exceptions¶
Good reasons:
- Feature provides significant value (e.g., advanced history search)
- Optimization would reduce functionality
- Plugin has no lazy-loading alternative
- Already at optimal speed for that type of operation
Bad reasons:
- Too lazy to investigate optimization
- Accepting poor performance as "normal"
- Not understanding the actual impact
Interpreting Recommendations¶
Plugin Optimization¶
Recommendation: "Lazy load {plugin} plugin"
What it means:
- Plugin loads during startup (blocking)
- Could be deferred until after prompt or first use
- Would save X milliseconds from perceived startup time
How to implement:
- Move plugin to deferred loading (loads after prompt):
- Or convert to lazy widget (loads on first use):
Core File Optimization¶
Recommendation: "Consider caching in core files"
What it means:
- Core initialization does expensive operations every startup
- Results could be cached and validated instead of regenerated
Example optimizations:
- Cache command existence checks
- Cache path validations
- Cache environment variable processing
Hook Optimization¶
Recommendation: "Review hook implementations"
What it means:
- Hooks run during startup and can accumulate time
- Some hook logic could be deferred or lazy-loaded
Common issues:
- Expensive API calls during startup
- Unnecessary file system operations
- Complex calculations that could be cached
Troubleshooting¶
Problem: "No timing data found"¶
Cause: Profile data hasn't been collected
Solution:
# Run profiling first
zprofile # Or zfull
# Then restart shell and generate report
exec zsh
zsh build/profile_bundle_report.zsh
Problem: "No valid timing data found (total_time=0)"¶
Cause: Profile log exists but contains no valid measurements
Possible reasons:
- Profile was interrupted
- Log file is corrupted
- Using incompatible profiling mode
Solution:
# Clear old profile data
rm ~/.cache/zshand/profile-timing.log
# Run fresh profile
zprofile
exec zsh
Problem: Report shows strange formatting¶
Cause: Terminal doesn't support box drawing characters or colors
Solutions:
- Use a modern terminal (kitty, alacritty, iTerm2, Windows Terminal)
- Ensure UTF-8 locale:
Problem: Exceptions not working¶
Possible causes:
- Pattern doesn't match
# Wrong: Using full path
/plugins/10-you-should-use.zsh|20|reason
# Right: Using basename only
10-you-should-use.zsh|20|reason
- Time threshold too low
# If plugin takes 16ms but threshold is 10ms
10-you-should-use.zsh|10|reason # Won't work
# Increase threshold
10-you-should-use.zsh|20|reason # Will work
- Syntax error in config
# Wrong: Missing delimiter
10-you-should-use.zsh 20 reason
# Right: Pipe-delimited
10-you-should-use.zsh|20|reason
Debug:
# Check if exceptions file is found
grep "exceptions_file=" build/profile_bundle_report.zsh
# Verify file content
cat config/profile-exceptions.conf
# Test pattern matching manually
pattern="10-you-should-use.zsh"
filename="/path/to/plugins/10-you-should-use.zsh"
[[ "${filename:t}" == ${~pattern} ]] && echo "Match!" || echo "No match"
Problem: Report takes too long to generate¶
Cause: Large profile log with many entries
Solutions:
- Profile log contains multiple sessions - this is normal
- Report processes all data but only shows latest
- To speed up, clear old data periodically:
# Keep only last 50 lines
tail -50 ~/.cache/zshand/profile-timing.log > /tmp/profile-timing.log
mv /tmp/profile-timing.log ~/.cache/zshand/profile-timing.log
Advanced Usage¶
Custom Cache Directory¶
# Profile with custom cache
ZSHAND_CACHE_DIR=/tmp/my-cache zprofile
# Generate report from custom cache
zsh build/profile_bundle_report.zsh /tmp/my-cache
Comparing Before/After Optimization¶
# 1. Generate baseline report
zprofile && exec zsh
zsh build/profile_bundle_report.zsh > before.txt
# 2. Make optimizations
# (edit configs, enable lazy loading, etc.)
# 3. Generate comparison report
rm ~/.cache/zshand/profile-timing.log
zprofile && exec zsh
zsh build/profile_bundle_report.zsh > after.txt
# 4. Compare
diff before.txt after.txt
# Or use: vimdiff before.txt after.txt
Continuous Monitoring¶
Set up periodic profiling to track performance over time:
# Add to your cron or systemd timer
# Profile weekly and save reports
0 0 * * 0 cd ~/code/zshand && zprofile
Best Practices¶
1. Profile Regularly¶
- After installing new plugins
- After major configuration changes
- Monthly for maintenance
2. Focus on High-Impact Items¶
- Optimize items marked HIGH IMPACT first
- Don't over-optimize items < 5ms
- Consider value vs. speed tradeoff
3. Document Exceptions¶
- Always include clear reasons in exception config
- Review exceptions periodically
- Remove exceptions when optimizations become available
4. Celebrate Wins¶
- The WINS section shows what's working well
- Don't feel pressure to optimize everything
- 100-150ms startup is excellent for feature-rich shells
5. Understand Context¶
- Async operations don't impact user experience
- First startup vs. subsequent startups may differ
- Some "slow" operations provide significant value
Related Documentation¶
docs/PROFILE_REPORT_REDESIGN.md- Design specificationdocs/DEFERRED_LAZY_DUAL_TIMING.md- Async loading systembuild/OPTIMIZATION_GUIDE.md- General optimization guide
Support¶
For issues or questions:
- Check Troubleshooting section above
- Review existing documentation
- Open an issue with:
- Your report output (or relevant sections)
- Your exception config (if using)
- Your shell environment (
echo $SHELL,zsh --version)