Skip to content

Refactor jax_fingerprint plugin for better modularity and fewer allocations#13072

Merged
maskit merged 14 commits intoapache:masterfrom
maskit:jax_refactor
Apr 10, 2026
Merged

Refactor jax_fingerprint plugin for better modularity and fewer allocations#13072
maskit merged 14 commits intoapache:masterfrom
maskit:jax_refactor

Conversation

@maskit
Copy link
Copy Markdown
Member

@maskit maskit commented Apr 8, 2026

Key changes:

  • datasource abstraction (JA4/JA4H) — provides accessor-based access to ClientHello fields, avoiding unnecessary copies into a summary object.
  • Eliminated temporary std::string allocations — helpers now write directly into caller-provided buffers and return std::string_view where possible. SHA256 hashing is done incrementally instead of materializing intermediate strings.
  • Small-array optimization — ciphers and extensions use stack storage for typical ClientHellos, falling back to heap only for unusually large ones.
  • ja4_common/ — shared utilities extracted for JA4 and JA4H.
  • Simplified headers — moved implementation details out of ja4.h; extracted tls_client_hello_summary.h as its own header.
  • Namespace cleanup — organized under proper namespaces.

Each subdirectory (ja3/, ja4/, ja4h/) now follows a consistent structure: method.cc/.h for the fingerprint method, test.cc for tests, plus algorithm-specific files. Redundant prefixes removed since subdirectories provide context.

Tests updated to match. No functional changes.

@maskit maskit added this to the 11.0.0 milestone Apr 8, 2026
@maskit maskit self-assigned this Apr 8, 2026
@maskit maskit added the Plugins label Apr 8, 2026
@maskit maskit requested a review from bneradt April 8, 2026 21:28
@maskit
Copy link
Copy Markdown
Member Author

maskit commented Apr 8, 2026

JA4 performance impact

Per fingerprint call (typical ClientHello with ~15 ciphers, ~15 extensions):

Allocation type Before After
Helper return strings (version, count, ALPN, hexify) ~10 + 2×N ciphers/extensions 0
Intermediate comma-separated string for hashing 2 0 (streaming SHA256)
Vector copies for sorting 2 0 (sort in place)
ALPN string copy 1 0 (string_view)
Result string 1 0 (caller buffer)

This eliminates 2–4 heap allocations and ~40 small-string construct/destruct cycles
per TLS connection. The per-connection savings are in the low-microsecond range —
modest compared to the TLS handshake itself, but meaningful in aggregate at high
connection rates (reduced allocator pressure and better cache utilization).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the experimental jax_fingerprint plugin’s JA3/JA4/JA4H implementations to use a more modular layout and reduce allocations by shifting to accessor-style datasources, incremental hashing, and shared utilities.

Changes:

  • Reorganized JA3/JA4/JA4H into consistent method.*, test.cc, and supporting files; updated plugin wiring and CMake sources.
  • Introduced JA4 datasource abstraction and TLSClientHelloSummary to avoid materializing intermediate strings/structures.
  • Extracted shared hashing helper(s) into ja4_common/ and updated unit tests accordingly.

Reviewed changes

Copilot reviewed 23 out of 25 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
plugins/experimental/jax_fingerprint/plugin.cc Updates includes and method selection to new namespaces/headers.
plugins/experimental/jax_fingerprint/CMakeLists.txt Updates build/test sources to new file layout; adds remap verification.
plugins/experimental/jax_fingerprint/ja4/ja4.h Simplifies public JA4 API to buffer-based generate_fingerprint() and constants.
plugins/experimental/jax_fingerprint/ja4/ja4.cc Reworks JA4 generation to write directly into caller buffer and use datasource-provided hashes.
plugins/experimental/jax_fingerprint/ja4/datasource.h Adds JA4 datasource interface and TLS/extension constants.
plugins/experimental/jax_fingerprint/ja4/datasource.cc Implements datasource helpers (GREASE detection, counts, SNI type).
plugins/experimental/jax_fingerprint/ja4/tls_client_hello_summary.h Adds TLS ClientHello-backed datasource with fast/slow storage paths.
plugins/experimental/jax_fingerprint/ja4/tls_client_hello_summary.cc Implements ClientHello parsing + incremental hashing for JA4 inputs.
plugins/experimental/jax_fingerprint/ja4/method.h Renames namespace/export for JA4 method entrypoint.
plugins/experimental/jax_fingerprint/ja4/method.cc New JA4 method implementation using TLSClientHelloSummary.
plugins/experimental/jax_fingerprint/ja4/test.cc Replaces previous JA4 tests with datasource-based unit tests.
plugins/experimental/jax_fingerprint/ja4/test_ja4.cc Removes old JA4 tests that depended on the prior summary object API.
plugins/experimental/jax_fingerprint/ja4/ja4_method.cc Removes old JA4 method implementation (replaced by ja4/method.cc).
plugins/experimental/jax_fingerprint/ja4_common/utils.h Adds shared helper declaration for truncating hash output to hex.
plugins/experimental/jax_fingerprint/ja4_common/utils.cc Implements shared hash-to-hex truncation helper.
plugins/experimental/jax_fingerprint/ja4h/ja4h.h Namespaces JA4H constants and renames generator API.
plugins/experimental/jax_fingerprint/ja4h/ja4h.cc Updates JA4H generator definition to new namespaced API.
plugins/experimental/jax_fingerprint/ja4h/method.h Renames JA4H namespace/export for method entrypoint.
plugins/experimental/jax_fingerprint/ja4h/method.cc Moves JA4H Method definition into the new namespace and updates calls.
plugins/experimental/jax_fingerprint/ja4h/test.cc Updates JA4H tests for namespaced constants and new API.
plugins/experimental/jax_fingerprint/ja3/method.h Renames JA3 namespace/export for method entrypoint.
plugins/experimental/jax_fingerprint/ja3/method.cc Updates JA3 method to include renamed headers and defines Method under ja3.
plugins/experimental/jax_fingerprint/ja3/utils.h Adds new JA3 utility API header (renamed from prior ja3_utils.*).
plugins/experimental/jax_fingerprint/ja3/utils.cc Adds new JA3 utility implementation file.
plugins/experimental/jax_fingerprint/ja3/test.cc Updates include to renamed JA3 utils header.
Comments suppressed due to low confidence (1)

plugins/experimental/jax_fingerprint/ja4h/test.cc:83

  • In this range-for over the map, auto ite copies each key/value pair. Use const auto &ite (or structured bindings with const auto &) to avoid unnecessary copies and keep the test closer to production-style allocation behavior.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 25 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

plugins/experimental/jax_fingerprint/ja4h/test.cc:84

  • for (auto ite : this->_fields) copies each std::pair<std::string, std::string>, causing unnecessary string allocations/copies during hashing. Iterate by reference instead (e.g., const auto &) to avoid the extra work.

@maskit
Copy link
Copy Markdown
Member Author

maskit commented Apr 8, 2026

Leak was detected during the regression tests but it looks unrelated to this change.

==5617==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 80 byte(s) in 1 object(s) allocated from:
    #0 0x7f8c4d479307 in operator new(unsigned long) (/lib64/libasan.so.6+0xb6307)
    #1 0xea09bb in Log::create_threads() ../src/proxy/logging/Log.cc:1214
    #2 0xea0323 in Log::init_when_enabled() ../src/proxy/logging/Log.cc:1163
    #3 0xea0667 in Log::load_config() ../src/proxy/logging/Log.cc:1183
    #4 0xab8eed in main ../src/traffic_server/traffic_server.cc:2377
    #5 0x7f8c4af89864 in __libc_start_main (/lib64/libc.so.6+0x3a864)

@maskit
Copy link
Copy Markdown
Member Author

maskit commented Apr 8, 2026

[approve ci rocky]

Copy link
Copy Markdown
Contributor

@bneradt bneradt left a comment

Choose a reason for hiding this comment

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

Looks good.

While we're at it, maybe should more stuff be in these ja3 and ja4 namespaces? Basically, every method would have all its content in a namespace. Thus, I notice that ja4_common/utils content is not in a ja4 namespace. Maybe that should?


Update: actually, you namespaced more than I realized in my earlier read. I think it's just ja4_common/ not namespaced, and that spans two "methods". So I am fine with how you have it now.

@maskit maskit merged commit ad2940c into apache:master Apr 10, 2026
15 checks passed
@maskit maskit deleted the jax_refactor branch April 10, 2026 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants