-
Notifications
You must be signed in to change notification settings - Fork 21
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
Implement VisibilityThresholdModifier #173
Implement VisibilityThresholdModifier #173
Conversation
cf92b10
to
4d8c789
Compare
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.
According to the screenshots, the device would heat more with the new approach, only the FPS is better, right?
@@ -159,18 +159,11 @@ public struct CallView<Factory: ViewFactory>: View { | |||
viewFactory.makeVideoParticipantsView( | |||
viewModel: viewModel, | |||
availableSize: size, | |||
onViewRendering: handleViewRendering(_:participant:), |
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.
Is it possible to do this without breaking changes to the public API?
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.
I remove this one as it's not being used anywhere. We can definitely go ahead without this change but makes our API confusing as we are asking for something what we won't be using.
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.
Other things to keep in mind when looking on the screenshots (as you may missed the note below them):
- The before screenshot shows lower consumption because the app at that point was unresponsive. Nothing was updating on the screen and that was causing consumption to drop.
- The after screenshot was captured after 55minutes in a call while the before it was on minute 18.
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.
ok, you should sell it better then 😄
The energy impact isn't really representative for the thermal state. The device feels cooler with the latest changes. That doesn't mean that processing video isn't an energy impactful operation. The difference is that it takes more time to jump the thermal state levels. |
b6c17b3
to
49dce2a
Compare
} else { | ||
VStack { | ||
participantsContent | ||
GeometryReader { geometryProxy in |
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.
Seems like we might have an extra geometry reader? The availableSize
value should also come from a geometry reader. Ideally, we should use only one.
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.
availableSize
is indeed coming from a GeometryReader in the CallView. We can't really use it here as we don't need only the size but the origin too.
We can potentially use only one GeometryReader but that will require a change on the API that will allow us to pass availableRect/availableViewport: CGRect
instead of availableSize: CGSize
.
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.
I would say it's better to break the API at this point, since we are still in beta. Geometry readers can be expensive, best to use them only when needed. Wdyt?
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.
Changing this one I think will incur many changes. How do you feel about having it in another PR?
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.
Maybe another PR towards this PR, to see how much it is? Since if we do breaking changes, we should do them very soon.
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.
A PR to this branch sounds good. Here it is #176
Sources/StreamVideoSwiftUI/CallView/VisibilityThresholdModifier.swift
Outdated
Show resolved
Hide resolved
Task { [weak self] in | ||
guard let self else { return } | ||
Task { [serialActor] in | ||
await serialActor.enqueue { [weak self] in |
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.
Not 100% sure why enqueuing async tasks helps performance, can you please elaborate one more time? 🙏
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.
The idea is that Tasks not running on a specific actor will run as part of the GlobalActor. The previous days I remember reading that the GlobalActor is concurrent. That meant that the Tasks created here (outside of an Actor) will run as part of the GlobalActor. As they will run concurrently we may doing processing for more that one frame at the same time which can be consuming.
However, looking again now I couldn't find what I was reading and i ended up asking ChatGPT. The answer is that the GlobalActor is serial. So I will remove this one.
To control whenever TrackViews will be taking up rendering tasks
3e63270
to
68f4c85
Compare
04371c5
to
a423ee4
Compare
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.
This one is higher as now we are using the frame from global and in the empty space is where we have the controls.
Generated by 🚫 Danger |
Kudos, SonarCloud Quality Gate passed! |
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.
lgtm! ✅
🎯 Goal
Reduce CPU usage demands during a call with more than 5 participants.
📝 Summary
When in a call with more than 5 participants we use a GridView to show and arrange video tracks. This view leverages the
onAppear
&onDisappear
hooks to disable tracks that are not on screen. Unfortunately, as we are usingLazyVStack
to wrap our video tracks, iOS preloads views that aren't on screen, resulting in rendering video tracks that aren't really on user's viewport.🛠 Implementation
To resolve this problem, we introduce a ViewModifier that internally uses a GeometryReader to compute if it's in its parent's viewport. If not the View is considered hidden and we propagate a visibility change that stops renderings for the View's video track.
🎨 Showcase
Add relevant screenshots and/or videos/gifs to easily see what this PR changes, if applicable.
Note
The smaller CPU Usage and Energy impact is because the app was unresponsive and render requests were dropping (as can be seen from the FPS counter).
🧪 Manual Testing Notes
Explain how this change can be tested manually, if applicable.
☑️ Contributor Checklist
🎁 Meme