From d5d28fb987676b03139c2a67ef3d9b0f15b159f9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 18:57:55 +0000 Subject: [PATCH] perf(lib): cache json processor detection Prevents redundant `command -v` checks in `safe_json_get_key` and other functions by caching the result in `_JSON_PROCESSOR_CACHE` upon sourcing `lib/core/common.sh`. Benchmark result: ~13% improvement (600ms -> 530ms for 100 iterations of `safe_json_get_key`). Performance journal updated in `.jules/bolt.md`. --- .jules/bolt.md | 3 +++ lib/core/common.sh | 43 +++++++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..67aa86b --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2026-01-16 - [Shell Dependency Check Overhead] +**Learning:** `lib/core/common.sh` functions like `safe_json_get_key` re-check dependencies (`command -v jq`) on every invocation. In tight loops, this adds significant overhead (~13% in micro-benchmark). +**Action:** Cache dependency checks in global variables (e.g., `_JSON_PROCESSOR_CACHE`) when the script is sourced, rather than checking inside hot functions. diff --git a/lib/core/common.sh b/lib/core/common.sh index 89c0646..e3e8c3b 100755 --- a/lib/core/common.sh +++ b/lib/core/common.sh @@ -74,14 +74,16 @@ safe_json_get_key() { return 1 fi - local processor="" - if command -v jq &> /dev/null; then - processor="jq" - elif command -v python3 &> /dev/null; then - processor="python3" - else - echo "$default" - return 1 + local processor="${_JSON_PROCESSOR_CACHE:-}" + if [ -z "$processor" ]; then + if command -v jq &> /dev/null; then + processor="jq" + elif command -v python3 &> /dev/null; then + processor="python3" + else + echo "$default" + return 1 + fi fi if [ "$processor" = "jq" ]; then @@ -134,11 +136,19 @@ safe_json_write() { if echo "$json_content" > "$temp_file" 2>&1; then # Validate JSON before moving local validation_failed=0 - if command_exists jq; then + local processor="${_JSON_PROCESSOR_CACHE:-}" + + # Fallback if not cached + if [ -z "$processor" ]; then + if command_exists jq; then processor="jq"; + elif command_exists python3; then processor="python3"; fi + fi + + if [ "$processor" = "jq" ]; then if ! jq . "$temp_file" > /dev/null 2>&1; then validation_failed=1 fi - elif command_exists python3; then + elif [ "$processor" = "python3" ]; then if ! python3 -m json.tool "$temp_file" > /dev/null 2>&1; then validation_failed=1 fi @@ -223,6 +233,11 @@ command_exists() { # Get JSON processor (jq, python3, or none) get_json_processor() { + if [ -n "${_JSON_PROCESSOR_CACHE:-}" ]; then + echo "$_JSON_PROCESSOR_CACHE" + return 0 + fi + if command_exists jq; then echo "jq" return 0 @@ -234,3 +249,11 @@ get_json_processor() { fi } +# Initialize JSON processor cache when sourced +if [ -z "${_JSON_PROCESSOR_CACHE:-}" ]; then + if command_exists jq; then + export _JSON_PROCESSOR_CACHE="jq" + elif command_exists python3; then + export _JSON_PROCESSOR_CACHE="python3" + fi +fi