-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Resolve circular reference in ThrottledFunc #9729
Conversation
ThrottledFunc previously created a DispatcherTimer whose Tick callback holds a strong reference to the DispatcherTimer itself. This causes a reference cycle, inadvertently leaking timer instances.
@@ -110,12 +90,29 @@ class ThrottledFunc : public std::enable_shared_from_this<ThrottledFunc<Args...> | |||
} | |||
|
|||
private: | |||
static winrt::fire_and_forget _Fire(winrt::Windows::Foundation::TimeSpan delay, winrt::Windows::UI::Core::CoreDispatcher dispatcher, std::weak_ptr<ThrottledFunc> weakThis) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: I've tried using a lambda instead of a static function, but the code turned out to be about as ugly (due to the need to explicitly capture every member variable). I've chosen the static function as it at least ensures that the this
pointer isn't accidentally used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great to me. Good point on avoiding accidental usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So cool that we got to move it to the header!
Pretty sure it has to say "Closes " for GitHub to automatically pick up the connection and tie them together. |
@miniksa I wasn't sure whether I should write that it closes that issue since we actually don't know what the cause for the severe slowdown is for the affected people. While we both can reproduce the timer leak locally, neither of us could reproduce a slowdown that causes such severe issues though, right? |
I was able to replicate the issue by running the following "slow cat" in 30 tabs simultaneously: cat big.txt | while read l; echo $l; sleep 0.05; end After about 10min the current store version started feeling sluggish, whereas this one didn't. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me pull this branch and do the heap trace to see if the leak is gone.
@@ -110,12 +90,29 @@ class ThrottledFunc : public std::enable_shared_from_this<ThrottledFunc<Args...> | |||
} | |||
|
|||
private: | |||
static winrt::fire_and_forget _Fire(winrt::Windows::Foundation::TimeSpan delay, winrt::Windows::UI::Core::CoreDispatcher dispatcher, std::weak_ptr<ThrottledFunc> weakThis) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great to me. Good point on avoiding accidental usage.
You're right that we're not 100% sure this will fix the issue for folks until they try it out, but we have a lot of reasons to be confident in it. It's a slow leak over time. It's on the UI dispatcher thread which makes everything slow. This throttler was introduced in June and the bug opened in September so by time proximity and the release schedule, it correlates. And the root cause and resolution make sense for the experience people are having. Also... we can always reopen the issue or duplicate it into a new one if we close it and it turns out to not work. So yeah. Just go for "Closes" when you're relatively confident. |
YES LEONARD'S FIRST PULL REQUEST |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EX CELLENT
@msftbot merge this in like 2ish minutes |
Hello @DHowett! I think you told me that you want to delay the approval for a certain amount of time, but I am not confident that I have understood you correctly. Please try rephrasing your instruction to me. |
@msftbot merge this in 1 minute |
Hello @DHowett! Because you've given me some instructions on how to help merge this pull request, I'll be modifying my merge approach. Here's how I understand your requirements for merging this pull request:
If this doesn't seem right to you, you can tell me to cancel these instructions and use the auto-merge policy that has been configured for this repository. Try telling me "forget everything I just told you". |
## Summary of the Pull Request ThrottledFunc previously created a DispatcherTimer whose Tick callback holds a strong reference to the DispatcherTimer itself. This causes a reference cycle, inadvertently leaking timer instances. ## PR Checklist * [x] Closes #7710 * [x] I work here ## Detailed Description of the Pull Request / Additional comments I've initially wanted to remove the `ThrottledFunc<>` optimization, but it turns out that this causes a 3% slowdown. That's definitely not a lot, but enough that we can just keep the optimization for the time being. I've moved the implementation from the .cpp file into the header regardless since the two implementations are extremely similar and it's easier that way to keep them in line. ## Validation Steps Performed I've ensured that the scrollbar still updates its length when I add new lines to a newly created tab. (cherry picked from commit faf372f)
🎉 Handy links: |
🎉 Handy links: |
Summary of the Pull Request
ThrottledFunc previously created a DispatcherTimer whose Tick callback holds a strong reference to the DispatcherTimer itself.
This causes a reference cycle, inadvertently leaking timer instances.
PR Checklist
Detailed Description of the Pull Request / Additional comments
I've initially wanted to remove the
ThrottledFunc<>
optimization, but it turns out that this causes a 3% slowdown. That's definitely not a lot, but enough that we can just keep the optimization for the time being.I've moved the implementation from the .cpp file into the header regardless since the two implementations are extremely similar and it's easier that way to keep them in line.
Validation Steps Performed
I've ensured that the scrollbar still updates its length when I add new lines to a newly created tab.