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

impr: Capture profiles on a BG Thread #4377

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

philipphofmann
Copy link
Member

📜 Description

Serializing and capturing a profile can run on the main thread and block it for a couple of milliseconds. Therefore, we move this to a background thread to avoid potentially blocking the main thread.

💡 Motivation and Context

This came up while investigating profiles for potentially slowing down UIViewControllers.

💚 How did you test it?

Unit test and checking if the profile is still correctly attached to UIViewController transactions with our iOS-Swift sample app.

📝 Checklist

You have to check all boxes before merging:

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

Serializing and capturing a profile can run on the main thread and block
it for a couple of milliseconds. Therefore, we move this to a background
thread to avoid potentially blocking the main thread.
Copy link

codecov bot commented Sep 30, 2024

Codecov Report

Attention: Patch coverage is 92.45283% with 4 lines in your changes missing coverage. Please review.

Project coverage is 91.454%. Comparing base (e88fe9a) to head (8eba803).

Files with missing lines Patch % Lines
...y/Profiling/SentryCaptureTransactionWithProfile.mm 78.947% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #4377       +/-   ##
=============================================
+ Coverage   91.450%   91.454%   +0.003%     
=============================================
  Files          629       630        +1     
  Lines        50625     50658       +33     
  Branches     18346     18358       +12     
=============================================
+ Hits         46297     46329       +32     
  Misses        4235      4235               
- Partials        93        94        +1     
Files with missing lines Coverage Δ
...es/Sentry/Profiling/SentryProfilerSerialization.mm 91.472% <100.000%> (+0.184%) ⬆️
Sources/Sentry/SentryTracer.m 96.912% <100.000%> (+0.167%) ⬆️
...SentryProfilerTests/SentryTraceProfilerTests.swift 98.905% <100.000%> (+0.074%) ⬆️
...y/Profiling/SentryCaptureTransactionWithProfile.mm 78.947% <78.947%> (ø)

... and 3 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e88fe9a...8eba803. Read the comment docs.

Copy link

github-actions bot commented Sep 30, 2024

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1222.76 ms 1240.08 ms 17.33 ms
Size 21.58 KiB 736.65 KiB 715.06 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
1bf8571 1250.96 ms 1255.36 ms 4.40 ms
2ccbd03 1225.13 ms 1247.51 ms 22.39 ms
d011484 1220.86 ms 1237.18 ms 16.33 ms
6001822 1220.82 ms 1245.02 ms 24.20 ms
3723833 1205.22 ms 1216.94 ms 11.71 ms
ff09c7e 1240.94 ms 1262.66 ms 21.72 ms
b9d59f7 1250.71 ms 1257.78 ms 7.06 ms
94d8eb3 1234.02 ms 1249.63 ms 15.60 ms
e773cad 1219.86 ms 1238.26 ms 18.40 ms
90d17d3 1261.18 ms 1278.18 ms 17.00 ms

App size

Revision Plain With Sentry Diff
1bf8571 20.76 KiB 437.12 KiB 416.36 KiB
2ccbd03 21.58 KiB 546.20 KiB 524.62 KiB
d011484 21.58 KiB 616.14 KiB 594.56 KiB
6001822 22.85 KiB 410.98 KiB 388.13 KiB
3723833 21.58 KiB 424.34 KiB 402.76 KiB
ff09c7e 20.76 KiB 427.76 KiB 407.00 KiB
b9d59f7 22.85 KiB 405.77 KiB 382.93 KiB
94d8eb3 21.58 KiB 417.86 KiB 396.28 KiB
e773cad 21.58 KiB 681.75 KiB 660.17 KiB
90d17d3 20.76 KiB 432.17 KiB 411.41 KiB

Copy link
Contributor

@brustolin brustolin left a comment

Choose a reason for hiding this comment

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

Thanks for this. There is one thing to discuss.

CHANGELOG.md Outdated Show resolved Hide resolved
Sources/Sentry/SentryTracer.m Outdated Show resolved Hide resolved
Copy link
Contributor

@brustolin brustolin left a comment

Choose a reason for hiding this comment

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

LGTM!

@philipphofmann
Copy link
Member Author

I'm still waiting for @armcknight to approve this so we can avoid shooting ourselves in the foot.

Copy link
Member

@armcknight armcknight left a comment

Choose a reason for hiding this comment

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

Could you be more specific about how you tested this? I just tried looking at a manual transaction with trace-based profiling on main vs this branch and the profiles look different. I can't get a launch profile to show up when running from this branch.

I tried comparing the differences between main and this branch with continuous profiling but I'm not even seeing what I expect on main so i need to ask the team what's going on there.

At a minimum for anything profiling right now you have to check what it looks like on main against your changes for:

  • trace-based
    • regular transaction
    • launch
  • continuous
    • regular transaction
    • launch

Trace-based regular txn on main (https://sentry-sdks.sentry.io/profiling/profile/sentry-cocoa/cdc0737ef92245a0b14dcdb40c5d68c3/flamegraph/?colorCoding=by%20system%20vs%20application%20frame&fov=0%2C0%2C3822472960%2C19&query=&sorting=call%20order&tid=259&view=top%20down):

image

and on this branch (https://sentry-sdks.sentry.io/profiling/profile/sentry-cocoa/28b4f9cc46ea4c2aa94cdfc400d11497/flamegraph/?colorCoding=by%20system%20vs%20application%20frame&fov=0%2C0%2C5127519744%2C19&query=&sorting=call%20order&tid=259&view=top%20down):

image

@philipphofmann
Copy link
Member Author

Hmm, weird, I didn't test it in great detail as I didn't expect that when all the tests are green, such a small change can have such a big impact. @armcknight, do you have a clue about what could cause this? I will look into this tomorrow.

@armcknight
Copy link
Member

@philipphofmann my guess is that you aren't dispatching the right call to the bg queue, and so it captures a set of profiling data much earlier than it marks the end of the transaction. You may need to look for a more granular point in that process, or create one by refactoring.

@philipphofmann
Copy link
Member Author

I found the problem. This PR only impacts trace based profiles, as only the SentryTracer uses sentry_traceProfileEnvelopeItem. Continuous profiling doesn't use this method.

I tested this for manual transactions, UIViewController transactions and app start transactions.

Main Branch This feature Branch
Manual Transaction CleanShot 2024-10-02 at 09 54 05@2x Profile in Sentry CleanShot 2024-10-02 at 09 55 03@2x Profile in Sentry
TransactionsViewController CleanShot 2024-10-02 at 09 56 06@2x Profile in Sentry CleanShot 2024-10-02 at 09 56 32@2x Profile in Sentry
App Start Transaction CleanShot 2024-10-02 at 09 58 00@2x Profile in Sentry CleanShot 2024-10-02 at 09 58 56@2x Profile in Sentry

return;
}

const auto profilingData = [profiler.state copyProfilingData];
Copy link
Member Author

Choose a reason for hiding this comment

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

@armcknight, when I move this into the async block the profiles the SDK shortens the profiles uploaded to Sentry, but I can't replicate this behavior in the testCaptureTransactionWithProfile_SetsCorrectAmountOfSamples. I would like to have a failing test for this to ensure we don't break this by mistake. Maybe the tests with the mocks behave differently than the actual profiling code, or I just don't get it.

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.

3 participants