Skip to content
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

fix(profiling): do not clear thread-loop link too often #3668

Merged
merged 9 commits into from
May 12, 2022

Conversation

jd
Copy link
Contributor

@jd jd commented May 4, 2022

The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.
@jd jd requested a review from a team as a code owner May 4, 2022 12:40
@codecov-commenter
Copy link

Codecov Report

Merging #3668 (c3d6c6c) into 1.x (c41d325) will decrease coverage by 0.04%.
The diff coverage is 28.57%.

@@            Coverage Diff             @@
##              1.x    #3668      +/-   ##
==========================================
- Coverage   78.11%   78.07%   -0.05%     
==========================================
  Files         645      646       +1     
  Lines       50014    50054      +40     
==========================================
+ Hits        39070    39081      +11     
- Misses      10944    10973      +29     
Impacted Files Coverage Δ
ddtrace/contrib/botocore/patch.py 89.94% <ø> (ø)
ddtrace/contrib/gevent/__init__.py 100.00% <ø> (ø)
ddtrace/internal/writer.py 83.91% <ø> (ø)
ddtrace/profiling/_asyncio.py 0.00% <ø> (ø)
tests/internal/test_utils_http.py 0.00% <0.00%> (ø)
ddtrace/internal/utils/http.py 52.94% <36.00%> (-47.06%) ⬇️
tests/conftest.py 93.14% <75.00%> (-0.47%) ⬇️

📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

@mergify mergify bot merged commit f583fec into DataDog:1.x May 12, 2022
@jd
Copy link
Contributor Author

jd commented May 12, 2022

@Mergifyio backport 1.0 0.x 1.1 0.60

mergify bot pushed a commit that referenced this pull request May 12, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)
mergify bot pushed a commit that referenced this pull request May 12, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)
mergify bot pushed a commit that referenced this pull request May 12, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)
mergify bot pushed a commit that referenced this pull request May 12, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)
@mergify
Copy link
Contributor

mergify bot commented May 12, 2022

Kyle-Verhoog pushed a commit that referenced this pull request May 13, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)

Co-authored-by: Julien Danjou <julien@danjou.info>
Co-authored-by: Gabriele N. Tornetta <P403n1x87@users.noreply.github.com>
Kyle-Verhoog pushed a commit that referenced this pull request May 13, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)

Co-authored-by: Julien Danjou <julien@danjou.info>
Co-authored-by: Gabriele N. Tornetta <P403n1x87@users.noreply.github.com>
Kyle-Verhoog pushed a commit that referenced this pull request May 13, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)

Co-authored-by: Julien Danjou <julien@danjou.info>
Kyle-Verhoog pushed a commit that referenced this pull request May 13, 2022
The current code calls DdtraceProfilerEventLoopPolicy.clear_threads each time a
task is resolved, which can be up to 100 times a second. This is way too much
and we don't expect for the thread->loop mapping to change that often.

Instead we often try to clear the mapping when a new loop is attached to a
thread. In a regular application, this is the expected workflow: a thread
appears and gets a new loop, so we clear the old ones.

The worst case scenario would be an app spawning 100 threads with 100 loops and
then not doing that ever again, which would make the profiler keep a reference
on the 100 loops — until a new loop is attached, which if never, would kept the
reference forever.

Since this far from being a common pattern, it should be safe to switch to a
simpler model like this.

(cherry picked from commit f583fec)

Co-authored-by: Julien Danjou <julien@danjou.info>
@brettlangdon brettlangdon added this to the v1.2.0 milestone May 17, 2022
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.

None yet

5 participants