Skip to content

Thread filter optim #238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

Thread filter optim #238

wants to merge 6 commits into from

Conversation

r1viollet
Copy link
Collaborator

  • Reserve padded slots
  • Introduce a register / unregister to retrieve slots
  • manage a free list

What does this PR do?:

Motivation:

Additional Notes:

How to test the change?:

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles
    credentials of any kind, I've requested a review from @DataDog/security-design-and-guidance.
  • This PR doesn't touch any of that.
  • JIRA: [JIRA-XXXX]

Unsure? Have a question? Request a review!

Copy link

github-actions bot commented Jul 7, 2025

🔧 Report generated by pr-comment-cppcheck

CppCheck Report

Errors (2)

Warnings (8)

Style Violations (306)

Copy link

github-actions bot commented Jul 7, 2025

🔧 Report generated by pr-comment-scanbuild

@r1viollet r1viollet force-pushed the r1viollet/thread_filter_squash branch 3 times, most recently from e5bce28 to 0918008 Compare July 7, 2025 11:45
@r1viollet
Copy link
Collaborator Author

I have reasonable performance on most runs:

Benchmark                                                       (command)  (skipResults)  (workload)  Mode  Cnt    Score   Error  Units
ThreadFilterBenchmark.threadFilterStress01  cpu=100us,wall=100us,filter=1           true           0  avgt         0.039          us/op
ThreadFilterBenchmark.threadFilterStress01  cpu=100us,wall=100us,filter=1           true           7  avgt         0.041          us/op
ThreadFilterBenchmark.threadFilterStress01  cpu=100us,wall=100us,filter=1           true       70000  avgt       111.094          us/op
ThreadFilterBenchmark.threadFilterStress02  cpu=100us,wall=100us,filter=1           true           0  avgt         0.132          us/op
ThreadFilterBenchmark.threadFilterStress02  cpu=100us,wall=100us,filter=1           true           7  avgt         0.139          us/op
ThreadFilterBenchmark.threadFilterStress02  cpu=100us,wall=100us,filter=1           true       70000  avgt       108.666          us/op
ThreadFilterBenchmark.threadFilterStress04  cpu=100us,wall=100us,filter=1           true           0  avgt         0.258          us/op
ThreadFilterBenchmark.threadFilterStress04  cpu=100us,wall=100us,filter=1           true           7  avgt         0.278          us/op
ThreadFilterBenchmark.threadFilterStress04  cpu=100us,wall=100us,filter=1           true       70000  avgt       118.940          us/op
ThreadFilterBenchmark.threadFilterStress08  cpu=100us,wall=100us,filter=1           true           0  avgt         0.624          us/op
ThreadFilterBenchmark.threadFilterStress08  cpu=100us,wall=100us,filter=1           true           7  avgt         0.646          us/op
ThreadFilterBenchmark.threadFilterStress08  cpu=100us,wall=100us,filter=1           true       70000  avgt       160.170          us/op
ThreadFilterBenchmark.threadFilterStress16  cpu=100us,wall=100us,filter=1           true           0  avgt         1.780          us/op
ThreadFilterBenchmark.threadFilterStress16  cpu=100us,wall=100us,filter=1           true           7  avgt         2.288          us/op
ThreadFilterBenchmark.threadFilterStress16  cpu=100us,wall=100us,filter=1           true       70000  avgt       221.987          us/op

I'm not sure why some runs still blow up for higher numbers of threads.

@r1viollet r1viollet mentioned this pull request Jul 7, 2025
3 tasks
@jbachorik jbachorik force-pushed the r1viollet/thread_filter_squash branch 2 times, most recently from e0ac246 to 2421ba9 Compare July 10, 2025 12:48
if (_thread_filter.enabled()) {
_thread_filter.remove(tid);
int slot_id = _thread_filter.registerThread();
current->setFilterSlotId(slot_id);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this code path should not happen, though I still need to think about whether it is safe if it happens (possible allocs)

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not happening in the signal context - this is a standard JVMTI callback - so allocation is fine here.
Also, I didn't really get the comment this code path should not happen - this is the path where we register newly created Java threads. This will happen quite often in a Java program.

}
ThreadFilter::SlotID ThreadFilter::popFromFreeList() {
// Lock-free sharded Treiber stack pop
int hash = static_cast<int>(std::hash<std::thread::id>{}(std::this_thread::get_id()));
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

interesting!

@r1viollet
Copy link
Collaborator Author

What is missing to merge this:

  • Think carefully about some of the error code paths
  • Run this in a test environment
  • Measure memory overhead

@jbachorik jbachorik force-pushed the r1viollet/thread_filter_squash branch from 2421ba9 to 50a8d5f Compare July 21, 2025 14:57
@jbachorik
Copy link
Collaborator

I did run some comparison of native memory usage with different thread filter implementations - data is in the notebook

TL;DR there is no observable increase in the native memory usage (the UNDEFINED category). Anyway, it would be useful to have an extra counter for the ThreadIDTable utilization.

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