Skip to content

perf(gap): inline 1-byte signed decode for TX Power Level#249

Merged
bdraco merged 3 commits into
Bluetooth-Devices:mainfrom
bluetoothbot:koan/inline-tx-power-decode
May 19, 2026
Merged

perf(gap): inline 1-byte signed decode for TX Power Level#249
bdraco merged 3 commits into
Bluetooth-Devices:mainfrom
bluetoothbot:koan/inline-tx-power-decode

Conversation

@bluetoothbot
Copy link
Copy Markdown
Contributor

@bluetoothbot bluetoothbot commented May 19, 2026

What

Drop the lru_cache(int.from_bytes(..., signed=True)) indirection for the TX Power Level AD branch. Decode the single signed byte inline with a typed unsigned char read and a signed-fold.

Why

The TX_POWER branch is already gated on end - start == 1 (added in #226 for spec compliance, Core Spec Vol 3 Part C §11). With that gate in place, _cached_from_bytes_signed(gap_data[start:end]) only ever decodes a one-byte slice — the slice allocation, hash, and cache lookup are pure overhead. A two-op signed-fold compiles to tight C in Cython.

How

  • Remove from_bytes_signed partial and the _cached_from_bytes_signed lru_cache wrapper from gap.py.
  • Replace the call with tx_power_byte = gap_data[start]; tx_power = tx_power_byte - 256 if tx_power_byte >= 128 else tx_power_byte.
  • Type tx_power_byte as unsigned char in gap.pxd so Cython folds the branch into native arithmetic.
  • Drop the matching cdef object from_bytes_signed / cdef object _cached_from_bytes_signed lines from gap.pxd.

Behaviour is unchanged: a one-byte 0xCE payload still decodes to -50, a multi-byte payload is still rejected (tx_power is None).

Testing

  • pytest tests/ --ignore=tests/benchmarks — 87 passed.
  • ruff check src/ — clean.
  • Cython compile sanity check against gap.py — no errors.
  • Existing test_parse_advertisement_data_tx_power_single_byte (-50) and test_parse_advertisement_data_tx_power_multibyte_rejected (None) cover both branches.

Quality Report

Changes: 2 files changed, 5 insertions(+), 7 deletions(-)

Code scan: clean

Tests: failed (FAILED)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

The TX_POWER branch is gated on `end - start == 1`, so the cached
`int.from_bytes(..., signed=True)` indirection only ever decoded a single
byte. Replace the slice + lru_cache + partial.from_bytes call chain with
a direct unsigned-char read and signed-fold (`b - 256 if b >= 128 else b`),
typed as `unsigned char` for Cython.

Drops `_cached_from_bytes_signed` and the `from_bytes_signed` partial,
along with their .pxd declarations. Behaviour is unchanged — the
spec-compliance gate added in Bluetooth-Devices#226 already enforces a 1-byte payload.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (3521434) to head (cf9a85a).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #249   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            6         6           
  Lines          254       255    +1     
  Branches        40        40           
=========================================
+ Hits           254       255    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 19, 2026

Merging this PR will improve performance by 4.91%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 2 improved benchmarks
✅ 9 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
test_parse_advertisement_data_tuple_bytes 73.4 µs 70 µs +4.92%
test_parse_advertisement_data_tuple_uncached 75.2 µs 71.7 µs +4.89%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing bluetoothbot:koan/inline-tx-power-decode (cf9a85a) with main (3521434)

Open in CodSpeed

@bdraco
Copy link
Copy Markdown
Member

bdraco commented May 19, 2026

@bluetoothbot rr

@bluetoothbot
Copy link
Copy Markdown
Contributor Author

PR Review — perf(gap): inline 1-byte signed decode for TX Power Level

Clean micro-optimization. The inline signed-fold (tx_power_byte - 256 if tx_power_byte >= 128 else tx_power_byte) is mathematically equivalent to int.from_bytes(..., signed=True) for a single byte, and the end - start == 1 gate from #226 guarantees the precondition. The unsigned char Cython typing folds the branch to native arithmetic. The .pxd cleanup correctly drops both cdef object declarations for the removed names — important per the project memory note about Cython exposing bogus None module attributes when stale cdef object decls linger. Existing tests (test_parse_advertisement_data_tx_power_single_byte for -50 = 0xCE, and the multibyte-rejected test) cover both branches and Codecov confirms 100% coverage. Merge-ready.



Checklist

  • Signed-byte decode is mathematically equivalent
  • Single-byte gate (end - start == 1) preserved
  • .pxd cleanup matches .py removals (no stale cdef object)
  • Cython type annotation correct (unsigned char)
  • Test coverage maintained (100% per Codecov)

Summary

Clean micro-optimization. The inline signed-fold (tx_power_byte - 256 if tx_power_byte >= 128 else tx_power_byte) is mathematically equivalent to int.from_bytes(..., signed=True) for a single byte, and the end - start == 1 gate from #226 guarantees the precondition. The unsigned char Cython typing folds the branch to native arithmetic. The .pxd cleanup correctly drops both cdef object declarations for the removed names — important per the project memory note about Cython exposing bogus None module attributes when stale cdef object decls linger. Existing tests (test_parse_advertisement_data_tx_power_single_byte for -50 = 0xCE, and the multibyte-rejected test) cover both branches and Codecov confirms 100% coverage. Merge-ready.


Automated review by Kōan111974f

@bluetoothbot
Copy link
Copy Markdown
Contributor Author

Rebase with requested adjustments

Branch koan/inline-tx-power-decode was rebased onto main and review feedback was applied.

Stats

2 files changed, 5 insertions(+), 7 deletions(-)
Actions performed
  • Already-solved check: negative (confidence=high, reasoning=Commit 259fe73 added the one-byte gate but kept the lru_cache decode path; no commit on main inlines)
  • Rebased koan/inline-tx-power-decode onto upstream/main
  • Pre-push CI check: previous run passed
  • Force-pushed koan/inline-tx-power-decode to origin
  • CI check enqueued in ## CI (async)

CI status

CI will be checked asynchronously.


Automated by Kōan

Comment thread src/bluetooth_data_tools/gap.py
Comment thread src/bluetooth_data_tools/gap.py Outdated
@bdraco
Copy link
Copy Markdown
Member

bdraco commented May 19, 2026

@bluetoothbot rr

@bluetoothbot
Copy link
Copy Markdown
Contributor Author

Rebase with requested adjustments

Branch koan/inline-tx-power-decode was rebased onto main and review feedback was applied.

Changes applied

  • Changes summary:
  • Extracted magic numbers 256 and 128 in the TX Power Level signed-fold to named module-level constants _INT8_RANGE and _INT8_SIGN_THRESHOLD in src/bluetooth_data_tools/gap.py per @bdraco's request ("could be a named const: uint8_t max const cdef and 128 could be as well").
  • Added matching cdef declarations in src/bluetooth_data_tools/gap.pxd (_INT8_SIGN_THRESHOLD as unsigned char, _INT8_RANGE as cython.uint) so Cython folds both into native integer arithmetic.
  • The other comment on line 109 ("clearly the cache is more expensive than the int convert") was reviewer agreement with the PR's premise, not a change request — no action taken.

Stats

2 files changed, 16 insertions(+), 7 deletions(-)
Actions performed
  • Already-solved check: negative (confidence=high, reasoning=Recent commits on main only added the one-byte gate (fix(gap): require exactly one signed byte for TX Power Level #227); none inline the signed decode or remove )
  • Rebased koan/inline-tx-power-decode onto upstream/main
  • Applied review feedback
  • Pre-push CI check: previous run passed
  • Force-pushed koan/inline-tx-power-decode to origin
  • CI check enqueued in ## CI (async)

CI status

CI will be checked asynchronously.


Automated by Kōan

@bdraco bdraco marked this pull request as ready for review May 19, 2026 21:12
@bdraco bdraco merged commit 45e9286 into Bluetooth-Devices:main May 19, 2026
49 checks passed
@bluetoothbot bluetoothbot deleted the koan/inline-tx-power-decode branch May 19, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants