Skip to content

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

  1. Generating a Profile Report
  2. Understanding the Report
  3. Performance Grading
  4. Configuring Exceptions
  5. Interpreting Recommendations
  6. 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|max_time_ms|reason
  • 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

  1. Report loads exceptions during startup
  2. When identifying slow operations, checks if they match exception patterns
  3. If time is within exception threshold, operation is filtered from recommendations
  4. 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:

  1. Move plugin to deferred loading (loads after prompt):
# In your plugins config
defer: true
  1. Or convert to lazy widget (loads on first use):
# Register lazy-loaded function
lazy_load_plugin "command-name" "plugin-path"

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:

  1. Profile was interrupted
  2. Log file is corrupted
  3. 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:

  1. Use a modern terminal (kitty, alacritty, iTerm2, Windows Terminal)
  2. Ensure UTF-8 locale:
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

Problem: Exceptions not working

Possible causes:

  1. 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
  1. 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
  1. 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:

  1. Profile log contains multiple sessions - this is normal
  2. Report processes all data but only shows latest
  3. 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


Support

For issues or questions:

  1. Check Troubleshooting section above
  2. Review existing documentation
  3. Open an issue with:
  4. Your report output (or relevant sections)
  5. Your exception config (if using)
  6. Your shell environment (echo $SHELL, zsh --version)