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

[SES-2021] Optimise XML loading #1512

Merged
merged 3 commits into from
Jun 21, 2024

Conversation

simophin
Copy link

Description

This PR tries to optimize some perspective of XML View loading, namely:

  1. Cache the expensive themeing operation that every View's initialization calls. (BaseActionBarActivity.getTheme()). I tested the theme changing it still works after the change.
  2. Adds a ViewPool to ConversactionActivityV2's RecyclerView.
  3. Lazy loads some views so that they only get inflated when in use
  4. Misc code tidy-up

@simophin simophin marked this pull request as ready for review June 11, 2024 03:41
@@ -1558,8 +1560,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe

if (indexInAdapter < 0 || indexInAdapter >= adapter.itemCount) { return }
val viewHolder = binding?.conversationRecyclerView?.findViewHolderForAdapterPosition(indexInAdapter) as? ConversationAdapter.VisibleMessageViewHolder ?: return
val visibleMessageView = ViewVisibleMessageBinding.bind(viewHolder.view).visibleMessageView
visibleMessageView.playVoiceMessage()
viewHolder.view.playVoiceMessage()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Have you tested this? The audio message plays without using that existing binding that was removed?

Copy link
Author

Choose a reason for hiding this comment

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

Yes I have tested.

The binding has been moved into the custom view itself

private val binding by lazy { ViewVisibleMessageBinding.bind(this) }
private val binding = ViewVisibleMessageBinding.inflate(LayoutInflater.from(context), this, true)

private val markerContainerBinding = lazy(LazyThreadSafetyMode.NONE) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why did you have to add the LazyThreadSafetyMode.NONE to those two bindings?

Copy link
Author

Choose a reason for hiding this comment

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

I find it wasteful to have a thread safe lazy for UI components where you only access through main thread.

@Module
@InstallIn(SingletonComponent::class)
class UiModule {
@Singleton
Copy link
Collaborator

Choose a reason for hiding this comment

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

I haven't used Pools before. Is that safe for it to be a singleton instantiated once? This never need to be cleared or anything?

Copy link
Author

Choose a reason for hiding this comment

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

I think you are right. Originally I had doubt about the memory leak perspective of using a global pool, at the end of the day, ViewHolders hold Views which hold Context under the hood. I thought Google should have thought about this and do some magical thing under the hood, until just now you prompted me to have a look again: oh well, nothing magical is happening in the pool so this is def a leaking point. I'm going to remove the use of the pool as they provide marginal benefit anyway. FYI @AL-Session

Copy link
Collaborator

Choose a reason for hiding this comment

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

More reasons for us to move this mammoth screen into Compose where we won't have to deal with recyclerviews and viewholders and adapters...

Copy link
Collaborator

@AL-Session AL-Session left a comment

Choose a reason for hiding this comment

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

Have tested & everything the PR touches that previously worked still appears to work, although it's difficult to quantify any performance changes without profiling.

I did notice that we're not specifying a size of the RecyclerViewPool and I believe the default max size is 5 (although I'm not seeing this 5 value referenced in modern docs - only in the first set of deprecated docs I came across). If we think of how many single line messages we can fit on a mobile device the number is probably closer to 13 - as such, would it be worth specifying that value as 13 via setMaxRecycledViews? (see: https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.RecycledViewPool)

Other than that query (feel free to address as you see fit) I'm perfectly happy to approve - nice job! =D

@simophin
Copy link
Author

Have tested & everything the PR touches that previously worked still appears to work, although it's difficult to quantify any performance changes without profiling.

I did notice that we're not specifying a size of the RecyclerViewPool and I believe the default max size is 5 (although I'm not seeing this 5 value referenced in modern docs - only in the first set of deprecated docs I came across). If we think of how many single line messages we can fit on a mobile device the number is probably closer to 13 - as such, would it be worth specifying that value as 13 via setMaxRecycledViews? (see: https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView.RecycledViewPool)

Other than that query (feel free to address as you see fit) I'm perfectly happy to approve - nice job! =D

The performance gain mainly comes from the first few enter into the conversation screen, and it's only obvious on a cheap device. I had printed out a few measurement, my Samsung used to take around 3-4 seconds to create the activity/message views and it's down to 1 second. Obviously there are still other things to do but they are much harder to do now.

@simophin simophin changed the base branch from master to dev June 21, 2024 02:52
@ThomasSession ThomasSession merged commit ba9f729 into oxen-io:dev Jun 21, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants