Skip to content

detect/thresh: expose threshold hash bucket depth stats#15098

Closed
jlucovsky wants to merge 4 commits intoOISF:mainfrom
jlucovsky:8401/2
Closed

detect/thresh: expose threshold hash bucket depth stats#15098
jlucovsky wants to merge 4 commits intoOISF:mainfrom
jlucovsky:8401/2

Conversation

@jlucovsky
Copy link
Copy Markdown
Contributor

Continuation of #15093

Add two new stats counters that report collision pressure in the threshold hash table:

  • detect.thresholds.max_bucket_depth — current maximum bucket depth across all buckets
  • detect.thresholds.avg_bucket_depth — average depth of non-empty buckets (total entries / non-empty buckets)

These counters allow operators to determine whether detect.thresholds.hash-size needs tuning. A consistently high
max_bucket_depth indicates hash collisions are degrading lookup performance. A low avg_bucket_depth with a high
max indicates skewed distribution into hot-spot buckets.

Link to ticket: https://redmine.openinfosecfoundation.org/issues/8401

Describe changes:

  • Add infrastructure for context-dependent counters
  • Expose threshold has bucket counters
  • Document value

Updates

  • Alphabetically sort added schema entries

Provide values to any of the below to override the defaults.

  • To use a Suricata-Verify or Suricata-Update pull request,
    link to the pull request in the respective _BRANCH variable.
  • Leave unused overrides blank or remove.

SV_REPO=
SV_BRANCH=OISF/suricata-verify#2985
SU_REPO=
SU_BRANCH=

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 25, 2026

Codecov Report

❌ Patch coverage is 93.63636% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.62%. Comparing base (448915f) to head (c18a3eb).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main   #15098    +/-   ##
========================================
  Coverage   82.61%   82.62%            
========================================
  Files         990      990            
  Lines      271581   271680    +99     
========================================
+ Hits       224375   224476   +101     
+ Misses      47206    47204     -2     
Flag Coverage Δ
fuzzcorpus 61.06% <63.88%> (-0.01%) ⬇️
livemode 18.40% <87.85%> (+0.04%) ⬆️
netns 18.37% <54.20%> (+0.01%) ⬆️
pcap 45.30% <91.58%> (+<0.01%) ⬆️
suricata-verify 66.17% <82.24%> (+<0.01%) ⬆️
unittests 58.85% <78.70%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@suricata-qa
Copy link
Copy Markdown

WARNING:

field baseline test %
SURI_TLPR1_stats_chk
.app_layer.flow.ftp-data 590 564 95.59%
.detect.thresholds.max_bucket_depth - 0 -
.detect.thresholds.avg_bucket_depth - 0 -

Pipeline = 30522

Comment thread src/counters.c
* \retval the counter id for the newly registered counter, or the already
* present counter on success
* \retval 0 on failure
* \param name Counter name (must outlive the counter).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this counters api stuff go into a separate commit?

Add StatsRegisterGlobalCounterWithContext() which passes a caller-
supplied context pointer to the getter function on each poll. This
allows multiple independent subsystems to share a single getter
implementation without requiring per-instance static wrappers.

Refactor counter registration to use a shared StatsFindOrAllocCounter()
helper, eliminating duplication between the standard and context-aware
registration paths. Move type assignment into the helper and fix a
double strrchr() call when computing short_name.

Issue: 8401
Add per-bucket length tracking, a nonempty_buckets atomic, and a
256-slot depth histogram to THashTableContext. The histogram enables
amortized O(1) computation of the current maximum bucket depth — the
value decreases as entries are removed, unlike a high-water mark.

THashBucketInsert/THashBucketRemove helpers consolidate bookkeeping
across all insert and remove sites. The walk-down path that lowers
max_bucket_depth re-checks the vacated histogram slot before the CAS
to avoid underreporting when a concurrent insert repopulates it.

Issue: 8401
Register detect.thresholds.max_bucket_depth and
detect.thresholds.avg_bucket_depth as global counters in
ThresholdRegisterGlobalCounters(), where stats_ctx is guaranteed
to be initialized.

Together, avg_bucket_depth shows overall collision pressure while
max_bucket_depth identifies pathological hot-spot buckets, helping
determine whether the hash function or table size needs tuning.

Update EVE JSON schema with the new fields.

Issue: 8401
Add a note to the threshold hash-size configuration section explaining
how the new avg_bucket_depth and max_bucket_depth counters can guide
hash-size tuning.

Issue: 8401
@jlucovsky
Copy link
Copy Markdown
Contributor Author

Continued in #15110

@jlucovsky jlucovsky closed this Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants