-
Notifications
You must be signed in to change notification settings - Fork 65
Implement command sidebar optimization to fix 15+ second build times #323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
6232b64
Initial plan
Copilot 7aaf34e
Implement cached command sidebar to fix build performance issue
Copilot 9876dc9
Clean up test data and update documentation for sidebar performance fix
Copilot ed10d10
Implement cached command sidebar using global variables instead of pr…
Copilot 6aaf88b
Implement pre-generation approach for commands sidebar to fix 15s bui…
Copilot 78a30d6
Remove all extra files and revert to original state
Copilot 7c8ffe8
Implement command sidebar optimization with pre-generation fallback
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Command Sidebar Optimization | ||
|
||
## Problem | ||
The original command page template had a performance issue where each command page would regenerate the complete sidebar by: | ||
1. Loading all command section pages (potentially 400+) | ||
2. For each page, attempting to load 4 different JSON files | ||
3. Processing all command data to build sidebar entries | ||
|
||
This resulted in O(n²) scaling where n = number of commands, leading to build times of 15+ seconds. | ||
|
||
## Solution | ||
Implemented a two-tier optimization approach: | ||
|
||
### 1. Pre-generation (Optimal) | ||
- `build/generate-commands-sidebar.py` processes all command JSON files once during build setup | ||
- Outputs `_data/commands_sidebar.json` containing pre-computed sidebar data | ||
- Template loads this single file instead of processing hundreds of JSON files per page | ||
- Reduces complexity from O(n²) to O(1) per page render | ||
|
||
### 2. Fallback (Graceful Degradation) | ||
- If pre-generated file doesn't exist, template falls back to original dynamic processing | ||
- Ensures the site builds correctly even without the optimization script | ||
- Maintains backward compatibility | ||
|
||
## Integration | ||
The optimization is integrated into `build/init-commands.sh` which runs the pre-generation script after creating command stub files. | ||
|
||
## Performance Impact | ||
- Expected build time reduction: 15+ seconds → <1 second for command processing | ||
- Eliminates quadratic scaling issue | ||
- Maintains identical sidebar functionality |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"commands": [] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
Generate commands sidebar data for Valkey documentation site. | ||
|
||
This script processes all command JSON files and creates a single | ||
_data/commands_sidebar.json file containing all command entries. | ||
This eliminates the need for the template to process hundreds of | ||
JSON files on every command page render. | ||
""" | ||
|
||
import json | ||
import os | ||
import sys | ||
from pathlib import Path | ||
|
||
|
||
def find_command_json_dirs(): | ||
"""Find all command JSON directories based on symlinks.""" | ||
base_dir = Path(".") | ||
json_dirs = [] | ||
|
||
for item in base_dir.iterdir(): | ||
if item.name.startswith("build-") and item.name.endswith("-command-json") and item.is_symlink(): | ||
json_dirs.append(item) | ||
|
||
return json_dirs | ||
|
||
|
||
def process_command_json(json_path, slug): | ||
"""Process a single command JSON file and extract relevant data.""" | ||
try: | ||
with open(json_path, 'r') as f: | ||
data = json.load(f) | ||
|
||
# Find the command object name (there should be only one key) | ||
command_obj_name = list(data.keys())[0] | ||
command_obj = data[command_obj_name] | ||
|
||
# Build command display name | ||
command_display = command_obj_name | ||
if command_obj.get("container"): | ||
command_display = f"{command_obj['container']} {command_display}" | ||
|
||
return { | ||
"display": command_display, | ||
"permalink": f"/commands/{slug}/", | ||
"summary": command_obj.get("summary", ""), | ||
"group": command_obj.get("group", "") | ||
} | ||
|
||
except (json.JSONDecodeError, KeyError, FileNotFoundError) as e: | ||
print(f"Warning: Could not process {json_path}: {e}", file=sys.stderr) | ||
return None | ||
|
||
|
||
def generate_commands_sidebar(): | ||
"""Generate the commands sidebar data file.""" | ||
commands_entries = [] | ||
|
||
# Find all command JSON directories | ||
json_dirs = find_command_json_dirs() | ||
|
||
if not json_dirs: | ||
print("Warning: No command JSON directories found", file=sys.stderr) | ||
# Create empty data file | ||
output_data = {"commands": []} | ||
else: | ||
# Process all JSON files in all directories | ||
for json_dir in json_dirs: | ||
if not json_dir.exists(): | ||
print(f"Warning: {json_dir} symlink target does not exist", file=sys.stderr) | ||
continue | ||
|
||
for json_file in json_dir.glob("*.json"): | ||
slug = json_file.stem | ||
command_data = process_command_json(json_file, slug) | ||
|
||
if command_data: | ||
commands_entries.append([ | ||
command_data["display"], | ||
command_data["permalink"], | ||
command_data["summary"], | ||
command_data["group"] | ||
]) | ||
|
||
output_data = {"commands": commands_entries} | ||
|
||
# Write the output file | ||
output_path = Path("_data/commands_sidebar.json") | ||
output_path.parent.mkdir(exist_ok=True) | ||
|
||
with open(output_path, 'w') as f: | ||
json.dump(output_data, f, indent=2) | ||
|
||
print(f"Generated {output_path} with {len(commands_entries)} commands") | ||
|
||
|
||
if __name__ == "__main__": | ||
generate_commands_sidebar() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this file.