Commit Graph

439 Commits

Author SHA1 Message Date
J. Nick Koston 587179143f Rename BENCHMARK_BINARY to BUILD_BINARY for generic use 2026-03-17 01:43:58 -10:00
J. Nick Koston b87b4102e0 Fix binary path extraction and defer benchmark compile error
- Use BENCHMARK_BINARY= marker for reliable binary path extraction
  instead of fragile tail -1 (PlatformIO can print warnings after path)
- Fix Scheduler_Defer: defer() is protected on Component, use
  set_timeout(delay=0) directly on Scheduler instead
2026-03-17 01:42:37 -10:00
J. Nick Koston 804e2330ec Ifdef out WarnIfComponentBlockingGuard for benchmark builds
Add USE_BENCHMARK define to benchmark build flags. Guard the
warn_blocking call in finish() with #ifndef USE_BENCHMARK so
scheduler benchmarks using fake monotonic time don't trigger
the underflow (fake now > real millis()).

Remove BenchComponent — no longer needed with the ifdef.
2026-03-17 01:16:34 -10:00
J. Nick Koston 1f9380ddc0 Fix scheduler firing benchmark: no inner loop, warm-up call
- Revert component.h change (no core changes for benchmarks)
- Remove -DWARN_IF_BLOCKING_OVER_MS from build flags (can't shadow constexpr)
- Drop inner loop — 5 heap pops + callbacks + pushes per call is well
  above CodSpeed's 60ns instrumentation overhead
- Add warm-up call before benchmark loop to trigger the blocking guard
  once and ramp the threshold
- interval=0 causes infinite loop, must use interval=1 with fake time
2026-03-17 01:05:04 -10:00
J. Nick Koston ec60e2c228 Fix scheduler benchmark: use fake time with guard disabled at compile time
interval=0 causes infinite loop (reschedules at same time, never breaks).
interval=1 with millis() doesn't work (real time doesn't advance fast
enough between inner iterations for intervals to re-fire).

Solution: use interval=1 with monotonically increasing fake time (now++)
and disable WarnIfComponentBlockingGuard at compile time via
-DWARN_IF_BLOCKING_OVER_MS=UINT32_MAX in benchmark build flags. This
prevents the guard's (millis() - started_) underflow when fake time
exceeds real millis().
2026-03-17 01:00:06 -10:00
J. Nick Koston 5d5a48c369 Fix _Fresh benchmark consistency and address review nits
- Remove inner loop from CalcAndEncode_DeviceInfoResponse_Fresh to match
  SensorStateResponse_Fresh — both now measure single alloc+encode per
  iteration as intended for heap allocation cost benchmarking
- Add comments documenting why _Fresh variants skip inner loops
- Add first-wins comment to load_component_yaml_configs
- Clean up .gitignore template comment
2026-03-16 23:52:27 -10:00
J. Nick Koston dd52c91290 Add inner iteration loops to amortize CodSpeed instrumentation overhead
Sub-microsecond benchmarks are dominated by the ~60ns per-iteration
valgrind start/stop cost in CodSpeed simulation mode. Add kInnerIterations
(1000) inner loops to all fast benchmarks so the actual work dominates.
Move DoNotOptimize calls outside inner loops to prevent artificial overhead.

Also address review feedback:
- Use tokenless CodSpeed (public repo, no CODSPEED_TOKEN needed)
- Fix warning message to show component-specific path
- Fix stray ". :" in error message
- Verify pinned SHA on re-runs to prevent stale checkouts
2026-03-16 23:32:49 -10:00
J. Nick Koston a92147e1c9 Remove BM_ prefix, drop application loop benchmark, fix core includes
- Remove BM_ prefix from all benchmark names (unnecessary convention)
- Remove bench_application_loop.cpp (App needs pre_setup/setup which
  requires full code generation; will revisit as integration benchmark)
- Fix extra_include_dirs to use os.path.relpath for sibling directories
2026-03-16 22:27:03 -10:00
J. Nick Koston 10e05b5efa Build all benchmark code with -O2 instead of -Os 2026-03-16 22:13:11 -10:00
J. Nick Koston 93991317c4 Build benchmark library with -O2 to inline instrumentation hooks 2026-03-16 22:08:22 -10:00
J. Nick Koston ea5f62f030 Add -DNDEBUG to benchmark builds
The benchmark library warns "Library was built as DEBUG" without NDEBUG.
This enables debug assertions and disables optimizations in the benchmark
framework, causing instrumentation overhead to show up in profiles.
2026-03-16 22:03:16 -10:00
J. Nick Koston 6b88820400 Remove debug logging now that CodSpeed is working 2026-03-16 21:59:36 -10:00
J. Nick Koston f7d4b437d0 Pin codspeed-cpp to v2.1.0 release tag 2026-03-16 21:58:52 -10:00
J. Nick Koston 63201d4437 Fix CodSpeed: use CODSPEED_ANALYSIS not CODSPEED_SIMULATION
CodSpeed's CMake uses CODSPEED_ANALYSIS (not CODSPEED_SIMULATION) for
simulation mode. This define gates all the actual benchmark measurement
hooks in benchmark_runner.cpp and benchmark.h. Without it, benchmarks
run normally but CodSpeed doesn't detect them as instrumented.
2026-03-16 21:55:53 -10:00
J. Nick Koston 374ca70f5b Add debug logging for CodSpeed build flags 2026-03-16 21:43:47 -10:00
J. Nick Koston cf672c1dc7 Add CODSPEED_ROOT_DIR to global build flags for relative paths in reports 2026-03-16 21:37:18 -10:00
J. Nick Koston b2e78d3753 Define CODSPEED_ENABLED globally for benchmark source files
benchmark.h uses #ifdef CODSPEED_ENABLED to switch benchmark
registration to CodSpeed-instrumented variants. This define was
only in library.json (applied to library compilation) but not to
the benchmark .cpp files that #include <benchmark/benchmark.h>.
Without it, CodSpeed reports "No benchmarks found".
2026-03-16 21:36:25 -10:00
J. Nick Koston 637180a628 Fix review issues: boolean comparison, missing trigger, constants
- Fix benchmarks CI condition: 'true' not 'True' (jq outputs lowercase)
- Add script/setup_codspeed_lib.py to benchmark infrastructure triggers
- Extract BENCHMARK_INFRASTRUCTURE_FILES and BENCHMARKS_COMPONENTS_PATH
  as top-level constants in determine-jobs.py
- Fix extra_include_dirs docstring
2026-03-16 21:30:00 -10:00
J. Nick Koston e7f1613159 Use shallow clone (depth 1) for codspeed-cpp 2026-03-16 21:26:22 -10:00
J. Nick Koston 0fc3fc2776 Clean up shared constants and setup script
- Move BASE_CODEGEN_COMPONENTS and USE_TIME_TIMEZONE_FLAG to test_helpers.py
- Use shared constants in both cpp_unit_test.py and cpp_benchmark.py
- Move json import to top level in cpp_benchmark.py
- Refactor setup_codspeed_lib.py into focused helper functions
- Combine clone + submodule init, use --shallow-submodules
2026-03-16 21:25:25 -10:00
J. Nick Koston f13513239d Fix CodSpeed instrumentation with PlatformIO
- Use CodSpeed's codspeed-cpp fork with proper instrumentation for
  simulation mode benchmark detection
- setup_codspeed_lib.py creates a flat PlatformIO-compatible library
  by combining google_benchmark sources, codspeed core, and
  instrument-hooks into a single library directory
- Renames .cc to .cpp (PlatformIO doesn't compile .cc by default)
- Adds all required defines: CODSPEED_ENABLED, CODSPEED_SIMULATION,
  CODSPEED_VERSION, CODSPEED_ROOT_DIR, CODSPEED_MODE_DISPLAY
- Output JSON config consumed by cpp_benchmark.py via env var
2026-03-16 21:21:44 -10:00
J. Nick Koston ff39fcbb94 Move CodSpeed library setup to Python script
Extract inline shell from CI workflow into script/setup_codspeed_lib.py.
Pins codspeed-cpp to a specific commit SHA for reproducibility.
2026-03-16 21:02:39 -10:00
J. Nick Koston 5cd2f58582 Use CodSpeed's codspeed-cpp fork for simulation mode
- Clone CodSpeed's codspeed-cpp repo (pinned to SHA) in CI
- Create PlatformIO-compatible library.json combining google_benchmark
  and codspeed core sources for proper instrumentation
- Pass library path via BENCHMARK_LIB env var to cpp_benchmark.py
- Use simulation mode for reproducible CPU instruction counting
- Locally, vanilla google/benchmark is used (no CodSpeed instrumentation)
2026-03-16 21:01:31 -10:00
J. Nick Koston a6219434b9 Move core benchmarks to tests/benchmarks/core/
Core is not a component — its benchmarks belong in tests/benchmarks/core/
not tests/benchmarks/components/core/. Add extra_include_dirs parameter
to build_and_run to support non-component benchmark directories.
2026-03-16 20:52:53 -10:00
J. Nick Koston 9c148da76a Add core benchmarks dir, fix core pseudo-component, use simulation mode
- Move scheduler/loop/helpers benchmarks to tests/benchmarks/components/core/
- Add random_float and random_uint32 benchmarks (from ol.yaml)
- Fix core pseudo-component crash: skip components where get_component()
  returns None when adding dependencies to config
- Use CodSpeed simulation mode (CPU instruction counting) for reproducible
  CI results instead of walltime
2026-03-16 20:49:48 -10:00
J. Nick Koston d9cab03c09 Move benchmarks into ci.yml with determine-jobs integration
- Add should_run_benchmarks() to determine-jobs.py that checks if
  directly changed components have benchmark files (no dependency
  expansion - changing sensor won't trigger api benchmarks)
- Move benchmark job from separate workflow into ci.yml
- Pin CodSpeed action to full commit SHA
- Delete separate ci-benchmarks.yml
2026-03-16 20:44:37 -10:00
J. Nick Koston 38ff332fec [core] Add CodSpeed C++ benchmarks for protobuf and main loop
Add automated benchmarks using Google Benchmark to prevent performance
regressions in the API protobuf encoding/decoding and core loop paths.

Benchmarks cover:
- Protobuf encode: SensorState, BinarySensorState, HelloResponse,
  LightState, DeviceInfoResponse (20 nested devices + 20 areas)
- Protobuf decode: HelloRequest, SwitchCommand, LightCommand
- Protobuf calculate_size and full calc+encode send path
- Varint parse/encode/size for various value ranges
- Scheduler call/next_schedule_in with idle and active timers
- Application loop component dispatch and blocking guard overhead

Infrastructure:
- Extract shared build logic from cpp_unit_test.py into test_helpers.py
- Add cpp_benchmark.py mirroring the unit test build pattern
- Support benchmark.yaml per component dir for declaring dependencies
- Add CodSpeed CI workflow triggered on api/core changes
- Fix ProtoMessage protected destructor on host platform
2026-03-16 19:25:46 -10:00
Jonathan Swoboda 18a082de30 [ci] Support URL and version extras in generate-esp32-boards.py (#14828)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-03-15 14:58:01 -04:00
J. Nick Koston 5e3c44d48f [rp2040] Add CI check for boards.py freshness (#14754)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-13 13:28:55 -10:00
J. Nick Koston 56f7b3e61b [ci] Only run integration tests for changed components (#14776) 2026-03-13 13:20:35 -10:00
J. Nick Koston 05d285ba86 [api] Fix heap-buffer-overflow in protobuf message dump for StringRef (#14721) 2026-03-12 07:16:53 -10:00
Adam DeMuri 4df3d3554e Enable the address and behavior sanitizers for C++ component unit tests (#13490) 2026-03-10 19:44:05 -10:00
J. Nick Koston 4d2ef09a29 [log] Detect early log calls before logger init and optimize hot path (#14538) 2026-03-10 09:12:10 -10:00
J. Nick Koston 6e468936ec [api] Inline ProtoVarInt::parse fast path and return consumed in struct (#14638)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 09:10:55 -10:00
Javier Peletier e82f0f4432 [cpptests] support testing platform components (#13075)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-03-10 02:41:02 +00:00
J. Nick Koston d6ce5dda81 [ci] Skip YAML anchor keys in integration fixture component extraction (#14670) 2026-03-09 22:54:56 +00:00
Clyde Stubbs f3ca86b670 [ci-custom] Directions on constant hoisting (#14637) 2026-03-08 23:48:03 -04:00
J. Nick Koston 088a8a4338 [ci] Match symbols with changed signatures in memory impact analysis (#14600)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 17:23:58 -10:00
tomaszduda23 e4b89a69d4 [nrf52, ota] ble and serial OTA based on mcumgr (#11932)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-03-07 20:32:20 -10:00
J. Nick Koston be6c3c52ac [api] Add force proto field option to skip zero checks on hot path (#14610)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:59:13 -10:00
J. Nick Koston 77f2c371b2 [api] Single-pass protobuf encode for BLE proxy advertisements (#14575) 2026-03-07 07:26:34 -10:00
J. Nick Koston 42dbb51022 [api] Devirtualize protobuf encode/calculate_size (#14449)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-06 19:03:54 +00:00
Kevin Ahrendt 5c5ea8824e [audio_file] New component for embedding files into firmware (#14434)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-03-05 09:51:08 -10:00
Clyde Stubbs f5c37bf486 [packet_transport] Minimise heap allocations (#14482) 2026-03-05 14:24:01 +11:00
J. Nick Koston 78602ccacb [ci] Add lint check to prevent powf in core and base entity platforms (#14126) 2026-03-03 07:03:50 -10:00
J. Nick Koston 1f1b20f4fe [core] Pack entity string properties into PROGMEM-indexed uint8_t fields (#14171) 2026-03-03 07:03:24 -10:00
J. Nick Koston f68a3ed15d [api] Remove virtual destructor from ProtoMessage (#14393) 2026-03-01 18:09:00 -10:00
J. Nick Koston b7cb65ec49 [ci] Fix TypeError in ci-custom.py when POST lint checks fail (#14378) 2026-02-28 14:23:20 -10:00
J. Nick Koston 5c56b99742 [ci] Fix C++ unit tests missing time component dependency (#14364) 2026-02-27 13:19:11 -10:00
J. Nick Koston 1ccfcfc8d8 [time] Eliminate libc timezone bloat (~9.5KB flash ESP32, ~2% RAM on ESP8266) (#13635)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:12:44 -10:00