Speed up shell startup 9x (1.9s → 0.2s)
Lazy-load Intel oneAPI setvars.sh (~1.5s) via wrapper functions that source the environment on first use of icc/icx/ifort/etc. Cache all shell completion outputs to ~/.cache/bash.d/ so they are sourced from disk instead of regenerated via subprocess on every shell start. Cache invalidates automatically when the tool binary is updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a9875dceec
commit
6a00847d4e
11 changed files with 83 additions and 23 deletions
25
00-completion-cache
Executable file
25
00-completion-cache
Executable file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# shellcheck shell=bash
|
||||||
|
# Cache completion scripts to avoid subprocess overhead on every shell start.
|
||||||
|
#
|
||||||
|
# Usage: cached_completion <tool> <generation-command...>
|
||||||
|
# Example: cached_completion gh gh completion -s bash
|
||||||
|
#
|
||||||
|
# The cache file is regenerated when the tool binary is newer than the cache.
|
||||||
|
# Cache location: ${XDG_CACHE_HOME:-$HOME/.cache}/bash.d/
|
||||||
|
|
||||||
|
_COMP_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/bash.d"
|
||||||
|
|
||||||
|
cached_completion() {
|
||||||
|
local tool="$1"; shift
|
||||||
|
local cache_file="${_COMP_CACHE}/${tool}.bash"
|
||||||
|
local tool_path
|
||||||
|
tool_path="$(command -v "$tool" 2>/dev/null)" || return
|
||||||
|
|
||||||
|
if [[ ! -f "$cache_file" || "$tool_path" -nt "$cache_file" ]]; then
|
||||||
|
mkdir -p "$_COMP_CACHE"
|
||||||
|
"$@" > "$cache_file" 2>/dev/null || return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$cache_file"
|
||||||
|
}
|
||||||
36
20-oneapi
36
20-oneapi
|
|
@ -1,13 +1,45 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# Intel oneAPI toolkit — source the environment setup if installed
|
# Intel oneAPI toolkit — lazy-loaded to avoid ~1.5s startup penalty.
|
||||||
# shellcheck disable=SC1090
|
# The full environment is sourced on first use of any Intel compiler/tool.
|
||||||
|
# To load manually: _load_oneapi
|
||||||
|
|
||||||
ONEAPI_SETVARS="/opt/intel/oneapi/setvars.sh"
|
ONEAPI_SETVARS="/opt/intel/oneapi/setvars.sh"
|
||||||
|
|
||||||
if [[ -f "$ONEAPI_SETVARS" ]]; then
|
if [[ -f "$ONEAPI_SETVARS" ]]; then
|
||||||
|
_load_oneapi() {
|
||||||
|
# Guard against double-loading
|
||||||
|
if [[ "${_ONEAPI_LOADED:-0}" -eq 1 ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
_ONEAPI_LOADED=1
|
||||||
|
|
||||||
|
# Remove the lazy-load wrappers before sourcing
|
||||||
|
local _cmd
|
||||||
|
for _cmd in icc icpc icx icpx ifort ifx dpcpp; do
|
||||||
|
unset -f "$_cmd" 2>/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
. "$ONEAPI_SETVARS" --force > /dev/null
|
. "$ONEAPI_SETVARS" --force > /dev/null
|
||||||
|
|
||||||
if [[ -n "$ONEAPI_ROOT" ]]; then
|
if [[ -n "$ONEAPI_ROOT" ]]; then
|
||||||
case ":${LD_LIBRARY_PATH}:" in
|
case ":${LD_LIBRARY_PATH}:" in
|
||||||
*":${ONEAPI_ROOT}/lib:"*) ;;
|
*":${ONEAPI_ROOT}/lib:"*) ;;
|
||||||
*) export LD_LIBRARY_PATH="${ONEAPI_ROOT}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ;;
|
*) export LD_LIBRARY_PATH="${ONEAPI_ROOT}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create wrapper functions for common Intel tools that trigger lazy-load
|
||||||
|
_oneapi_lazy_wrap() {
|
||||||
|
local cmd="$1"
|
||||||
|
# shellcheck disable=SC2139
|
||||||
|
eval "${cmd}() { _load_oneapi; command ${cmd} \"\$@\"; }"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _oneapi_cmd in icc icpc icx icpx ifort ifx dpcpp; do
|
||||||
|
_oneapi_lazy_wrap "$_oneapi_cmd"
|
||||||
|
done
|
||||||
|
unset -f _oneapi_lazy_wrap
|
||||||
|
unset _oneapi_cmd
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# shellcheck disable=SC1090
|
|
||||||
# Tab completion for asdf, a tool that manages multiple language runtime versions
|
# Tab completion for asdf, a tool that manages multiple language runtime versions
|
||||||
command -v asdf &>/dev/null && . <(asdf completion bash)
|
cached_completion asdf asdf completion bash
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# shellcheck disable=SC1090
|
|
||||||
# Enable bash completion for bun (JavaScript runtime & package manager)
|
# Enable bash completion for bun (JavaScript runtime & package manager)
|
||||||
command -v bun &>/dev/null && . <(bun completions)
|
cached_completion bun bun completions
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# shellcheck disable=SC1090
|
|
||||||
# Tab completion for fj, the Forgejo CLI (like GitHub CLI but for Forgejo)
|
# Tab completion for fj, the Forgejo CLI (like GitHub CLI but for Forgejo)
|
||||||
command -v fj &>/dev/null && . <(fj completion bash)
|
cached_completion fj fj completion bash
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# shellcheck disable=SC1090
|
|
||||||
# Tab completion for gh, the GitHub CLI
|
# Tab completion for gh, the GitHub CLI
|
||||||
command -v gh &>/dev/null && . <(gh completion -s bash)
|
cached_completion gh gh completion -s bash
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# shellcheck disable=SC1090
|
|
||||||
# Tab completion for Podman, a rootless container engine
|
# Tab completion for Podman, a rootless container engine
|
||||||
command -v podman &>/dev/null && . <(podman completion bash)
|
cached_completion podman podman completion bash
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# shellcheck disable=SC1090
|
|
||||||
# Tab completion for Tailscale, a mesh VPN for connecting devices
|
# Tab completion for Tailscale, a mesh VPN for connecting devices
|
||||||
command -v tailscale &>/dev/null && . <(tailscale completion bash)
|
cached_completion tailscale tailscale completion bash
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# Enable bash completion for uv (Python package manager)
|
# Enable bash completion for uv (Python package manager)
|
||||||
command -v uv &>/dev/null && eval "$(uv generate-shell-completion bash)"
|
cached_completion uv uv generate-shell-completion bash
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ Use these in all scripts — do not manipulate `PATH` or check permissions manua
|
||||||
- `path_append <dir>` — add directory to end of `$PATH` (checks existence, prevents duplicates)
|
- `path_append <dir>` — add directory to end of `$PATH` (checks existence, prevents duplicates)
|
||||||
- `path_prepend <dir>` — add directory to start of `$PATH`
|
- `path_prepend <dir>` — add directory to start of `$PATH`
|
||||||
- `require_private <file>` — warn if file is group/world-accessible; use in credential files
|
- `require_private <file>` — warn if file is group/world-accessible; use in credential files
|
||||||
|
- `cached_completion <tool> <gen-cmd...>` — cache completion output to `~/.cache/bash.d/`; regenerates when the tool binary is updated. Use this for all new completion scripts instead of `eval` or `. <()`
|
||||||
|
|
||||||
## Writing Scripts
|
## Writing Scripts
|
||||||
|
|
||||||
|
|
@ -30,6 +31,8 @@ Use these in all scripts — do not manipulate `PATH` or check permissions manua
|
||||||
- Guard directory-dependent exports with `[[ -d <path> ]]` before exporting
|
- Guard directory-dependent exports with `[[ -d <path> ]]` before exporting
|
||||||
- Do not suppress stderr from external scripts — only redirect stdout when needed
|
- Do not suppress stderr from external scripts — only redirect stdout when needed
|
||||||
- Avoid `eval` when `. <(cmd)` (process substitution) works
|
- Avoid `eval` when `. <(cmd)` (process substitution) works
|
||||||
|
- For shell completions, use `cached_completion` instead of `eval` or `. <()` to avoid subprocess overhead on every shell start
|
||||||
|
- For slow environment scripts, use lazy-loading (see `20-oneapi` for the wrapper-function pattern)
|
||||||
- Prevent `LD_LIBRARY_PATH` duplicates with a `case` guard (see `20-oneapi` for example)
|
- Prevent `LD_LIBRARY_PATH` duplicates with a `case` guard (see `20-oneapi` for example)
|
||||||
|
|
||||||
## Permissions
|
## Permissions
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ Lower numbers load first, so foundational pieces like helper functions (`00-`) a
|
||||||
|
|
||||||
- **`00-path-helper`** — Defines `path_append` and `path_prepend` functions that safely add directories to `$PATH` (checking the directory exists and avoiding duplicates).
|
- **`00-path-helper`** — Defines `path_append` and `path_prepend` functions that safely add directories to `$PATH` (checking the directory exists and avoiding duplicates).
|
||||||
- **`00-credential-guard`** — Defines `require_private`, which warns at shell startup if a credential file has overly permissive permissions (anything beyond owner-only access).
|
- **`00-credential-guard`** — Defines `require_private`, which warns at shell startup if a credential file has overly permissive permissions (anything beyond owner-only access).
|
||||||
|
- **`00-completion-cache`** — Defines `cached_completion`, which caches shell completion scripts to `~/.cache/bash.d/` so they are only regenerated when the tool binary is updated. Used by all `50-*-completion` scripts.
|
||||||
|
|
||||||
### PATH (`10-`)
|
### PATH (`10-`)
|
||||||
|
|
||||||
|
|
@ -46,7 +47,7 @@ Lower numbers load first, so foundational pieces like helper functions (`00-`) a
|
||||||
|
|
||||||
- **`20-android`** — Sets `$ANDROID_HOME`, `$JAVA_HOME`, and adds Android SDK tools to PATH (only when installed).
|
- **`20-android`** — Sets `$ANDROID_HOME`, `$JAVA_HOME`, and adds Android SDK tools to PATH (only when installed).
|
||||||
- **`20-ninja`** — Configures Ninja as the default CMake generator and enables ccache for C/C++ builds (only when installed).
|
- **`20-ninja`** — Configures Ninja as the default CMake generator and enables ccache for C/C++ builds (only when installed).
|
||||||
- **`20-oneapi`** — Sources the Intel oneAPI environment and adds its libraries to `LD_LIBRARY_PATH`.
|
- **`20-oneapi`** — Lazy-loads the Intel oneAPI environment. Because `setvars.sh` takes ~1.5 seconds, the full environment is deferred until an Intel tool (`icc`, `icx`, `ifort`, etc.) is first invoked. Call `_load_oneapi` to trigger it manually.
|
||||||
|
|
||||||
### Prompt (`30-`)
|
### Prompt (`30-`)
|
||||||
|
|
||||||
|
|
@ -54,9 +55,14 @@ Lower numbers load first, so foundational pieces like helper functions (`00-`) a
|
||||||
|
|
||||||
### Completions (`50-`)
|
### Completions (`50-`)
|
||||||
|
|
||||||
|
All completions (except `50-claude-completion`) use `cached_completion` to avoid subprocess overhead on every shell start. Cache files live in `~/.cache/bash.d/` and are automatically regenerated when the tool binary is updated.
|
||||||
|
|
||||||
- **`50-asdf-completion`** — Tab completion for the asdf version manager.
|
- **`50-asdf-completion`** — Tab completion for the asdf version manager.
|
||||||
|
- **`50-bun-completion`** — Tab completion for Bun (JavaScript runtime & package manager).
|
||||||
- **`50-claude-completion`** — Tab completion for [Claude Code](https://claude.com/claude-code) CLI.
|
- **`50-claude-completion`** — Tab completion for [Claude Code](https://claude.com/claude-code) CLI.
|
||||||
- **`50-fj-completion`** — Tab completion for the Forgejo CLI (`fj`).
|
- **`50-fj-completion`** — Tab completion for the Forgejo CLI (`fj`).
|
||||||
|
- **`50-gh-completion`** — Tab completion for the GitHub CLI (`gh`).
|
||||||
|
- **`50-podman-completion`** — Tab completion for Podman (rootless container engine).
|
||||||
- **`50-tailscale-completion`** — Tab completion for Tailscale.
|
- **`50-tailscale-completion`** — Tab completion for Tailscale.
|
||||||
- **`50-uv-completion`** — Tab completion for [uv](https://github.com/astral-sh/uv) (Python package manager).
|
- **`50-uv-completion`** — Tab completion for [uv](https://github.com/astral-sh/uv) (Python package manager).
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue