Optimize authority_checker hot paths for transaction authorization#258
Optimize authority_checker hot paths for transaction authorization#258
Conversation
- Add fast-path for single-key authorities (most common case), bypassing meta_permission_map allocation and rollback overhead (~37% faster) - Add fast-path for threshold-1 multi-key authorities (e.g. 1-of-3), returning on first matching key (~46% faster) - Replace linear key search (boost::find) with binary search (std::lower_bound) on the already-sorted provided_keys vector, yielding up to 55% improvement for large key sets - Switch permission_cache_type from std::map to flat_map for better cache locality with typical small permission sets - Short-circuit irrelevant-auth check in authorization_manager when declared permission name matches the minimum, avoiding redundant DB lookups and hierarchy walks on the most common code path - Add resolve_key() helper for type-safe shared_public_key conversion - Add auth benchmark suite covering single-key, multi-sig, large key sets, and recursive permission resolution scenarios
There was a problem hiding this comment.
Pull request overview
This PR optimizes hot paths in authority_checker and related authorization checks to reduce transaction authorization overhead, and adds a dedicated authorization benchmark suite to track performance changes.
Changes:
- Add fast paths for common key-only authorities and switch key matching to binary search over sorted
provided_keys. - Replace the permission cache from
std::maptoflat_mapand adjust recursion logic to handle iterator invalidation. - Add an
authbenchmark feature with scenarios covering single-key, multisig, large key sets, and recursive resolution.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| libraries/chain/include/sysio/chain/authority_checker.hpp | Adds fast paths, binary-search key lookup, and changes permission cache to flat_map. |
| libraries/chain/authorization_manager.cpp | Skips irrelevant-auth hierarchy checks when declared permission already equals the minimum. |
| benchmark/benchmark.hpp | Declares auth_benchmarking() entry point. |
| benchmark/benchmark.cpp | Registers auth as a runnable benchmark feature. |
| benchmark/auth.cpp | Implements new authorization microbenchmarks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Re-lookup after recursive call (flat_map iterators may be invalidated) | ||
| auto cache_itr = cached_permissions.find( permission.permission ); | ||
| assert( cache_itr != cached_permissions.end() ); | ||
| if( r ) { | ||
| total_weight += permission.weight; | ||
| itr->second = permission_satisfied; | ||
| cache_itr->second = permission_satisfied; | ||
| } else { | ||
| itr->second = permission_unsatisfied; | ||
| cache_itr->second = permission_unsatisfied; |
There was a problem hiding this comment.
assert(cache_itr != cached_permissions.end()) is used in this header without including <cassert>, which can cause compilation failures depending on include order. Also, in Release builds with NDEBUG, the assert is compiled out and cache_itr->second = ... would be undefined behavior if the lookup ever failed; prefer a non-elided check (e.g., SYS_ASSERT/SYS_THROW) or an explicit if (cache_itr == end) ... fallback, and add the proper header if you keep assert.
Summary
meta_permission_mapallocation and rollback overhead for the most common case (single key, no account references)boost::findwithstd::lower_boundon the already-sortedprovided_keysvectorpermission_cache_typefromstd::maptoflat_mapfor better cache locality with typical small permission setsauthorization_manager::check_authorizationwhen declared permission name matches the minimum (the common case)Benchmark Results (Release build, 10k runs, minimum ns)
Multi-sig 2-of-3/3-of-5 show a small ~5% regression from
std::lower_bound'soperator<vsboost::find'soperator==at small N. The absolute cost increase is ~4-5ns, dwarfed by the gains on the dominant single-key and threshold-1 paths.