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

[experiment] limit number of rendered messages when open a chat #8191

Merged
merged 1 commit into from
May 22, 2019

Conversation

rasom
Copy link
Member

@rasom rasom commented May 12, 2019

  • Currently we render 20 last messages when chat is opened first time, if we have more messages loaded we render all of them. Having much more than 20 messages doesn't affect performance of flat list too drastically because most of items which are not viewable are not drawn. At the same time ~20 message currently produce 2200-2400 calls to UIManager through bridge. These calls are not too expensive per se (drawing is more expensive) but still cost some time on js thread and we don't limit them (having 200 loaded messages means much more such calls -> js thread loaded with unnecessary work).
  • In this pr we limit number of rendered messages to 5, if it is not enough to 11 and then 20. After that we add 20 more messages to stream when necessary. This 5-11-20 limit is re-applied each time the chat is opened, which means that even if we already loaded 500 messages they will not contribute to total number of UIManager calls during navigation, only when user will scroll messages.

Results:

navigation from chat list to chat (#status) w/o opacity wrapper, galaxy s9

  • 20 messages without limit: 0.43-0.6s
  • 20 messages with limit: 0.24s; 45% faster

navigation from chat list to chat with opacity wrapper, galaxy s9

  • 20 messages without limit: 0.53s (0.16s <- for switching screens)
  • 20 messages with limit: 0.27s (0.16s <- for switching screens) 49% faster

navigation from chat list to chat (#status) w/o opacity wrapper, galaxy a500d (slower device)

  • 20 messages without limit: 1.8s
  • 20 messages with limit: 1.234s; 31% faster

navigation from chat list to chat with opacity wrapper, galaxy a500d (slower device)

  • 20 messages without limit: 2.1s (0.54s <- for switching screens)
  • 20 messages with limit: 1.34s (0.54s <- for switching screens) 36% faster

Navigation from chats list to chat is 30-45% faster.

@status-github-bot
Copy link

Pull Request Checklist

  • Have you updated the documentation, if impacted (e.g. docs.status.im)?

@status-github-bot status-github-bot bot added this to REVIEW in Pipeline for QA May 12, 2019
@status-im-auto
Copy link
Member

status-im-auto commented May 12, 2019

Jenkins Builds

Click to see older builds (18)
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ a3a2f27 #1 2019-05-12 06:13:43 ~15 min android-e2e 📦 apk
✔️ a3a2f27 #1 2019-05-12 06:16:22 ~18 min macos 📦 dmg
✔️ a3a2f27 #1 2019-05-12 06:16:36 ~18 min windows 📦 exe
✔️ a3a2f27 #1 2019-05-12 06:20:31 ~22 min android 📦 apk
✔️ a3a2f27 #1 2019-05-12 06:21:02 ~23 min linux 📦 App
✔️ a3a2f27 #1 2019-05-12 06:21:04 ~23 min ios 📦 ipa
✔️ 5d050ec #2 2019-05-12 09:29:02 ~14 min android 📦 apk
✔️ 5d050ec #2 2019-05-12 09:31:24 ~17 min windows 📦 exe
✔️ 5d050ec #2 2019-05-12 09:31:52 ~17 min macos 📦 dmg
✔️ 5d050ec #2 2019-05-12 09:36:15 ~21 min android-e2e 📦 apk
✔️ 5d050ec #2 2019-05-12 09:36:17 ~21 min linux 📦 App
✔️ 5d050ec #2 2019-05-12 09:37:34 ~23 min ios 📦 ipa
✔️ d1d5eea #3 2019-05-12 15:27:58 ~14 min android 📦 apk
✔️ d1d5eea #3 2019-05-12 15:32:40 ~19 min windows 📦 exe
✔️ d1d5eea #3 2019-05-12 15:33:08 ~19 min macos 📦 dmg
✔️ d1d5eea #3 2019-05-12 15:37:09 ~23 min ios 📦 ipa
✔️ d1d5eea #3 2019-05-12 15:37:56 ~24 min android-e2e 📦 apk
✔️ d1d5eea #3 2019-05-12 15:38:01 ~24 min linux 📦 App
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 7b5f19a #4 2019-05-22 06:41:15 ~18 min macos 📦 dmg
✔️ 7b5f19a #4 2019-05-22 06:42:40 ~20 min windows 📦 exe
✔️ 7b5f19a #4 2019-05-22 06:43:43 ~21 min android-e2e 📦 apk
✔️ 7b5f19a #4 2019-05-22 06:44:18 ~21 min linux 📦 App
✔️ 7b5f19a #4 2019-05-22 06:44:43 ~22 min android 📦 apk
✔️ 7b5f19a #4 2019-05-22 06:45:53 ~23 min ios 📦 ipa
✔️ 932ef27 #5 2019-05-22 14:18:27 ~18 min android 📦 apk
✔️ 932ef27 #5 2019-05-22 14:18:41 ~19 min android-e2e 📦 apk
✔️ 932ef27 #5 2019-05-22 14:24:30 ~24 min ios 📦 ipa

@flexsurfer
Copy link
Member

flexsurfer commented May 13, 2019

just wondering why is it so ~20 message currently produce 2200-2400 calls ? maybe we could optimize message itself?

@@ -299,6 +344,8 @@
:on-layout (fn [e]
(re-frame/dispatch [:set :layout-height (-> e .-nativeEvent .-layout .-height)]))}
[chat-toolbar current-chat public? modal?]
[react/text {:style {:height 14}}
Copy link
Member

Choose a reason for hiding this comment

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

leftover?

Copy link
Member Author

@rasom rasom May 13, 2019

Choose a reason for hiding this comment

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

in current build when you open chat screen first time limit enabled: true is shown which means it is rendered with new limits, the next time limit enabled: false is shown - that's an old version. Just for testing

Copy link
Member

Choose a reason for hiding this comment

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

i mean, do you plan to remove this after testing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure

@rasom
Copy link
Member Author

rasom commented May 13, 2019

just wondering why is it so ~20 message currently produce 2200-2400 calls ? maybe we could optimize message itself?

yep I have a branch in progress with 18-20% improvement on this number. We definitely have some redundant components there. But still impact of such changes will be much less noticeable


(defn increment-limit [lim]
(+ lim
(cond
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe better to use case here and put the numerical values directly

Copy link
Member Author

Choose a reason for hiding this comment

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

how is it better?

Copy link
Contributor

@yenda yenda May 20, 2019

Choose a reason for hiding this comment

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

case is an order of magnitude faster, and that not even considering that you are doing some additions here in the conditions that are not sure can be optimize by the compiler

(case lim
     ;; first step
     5 11
     ;; second step
     11 16
     ;; next steps
     (+ lim 20)
status-im.wallet.custom-tokens.core>  (time (dotimes [x 10000000] (cond (= x 1) 2 (= x 3) 4 :else 5)))
"Elapsed time: 5275.000000 msecs"
nil
status-im.wallet.custom-tokens.core> (time (dotimes [x 10000000] (case x 1 2 3 4 5)))
"Elapsed time: 24.000000 msecs"
nil

Copy link
Member Author

Choose a reason for hiding this comment

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

  1. relying on magic numbers is going to be an issue, I prefer to avoid doing this. If values are co-dependent, that should be expressed in the code.
  2. The difference in efficiency in negligible compering to the whole rendering thing as long as this operation is not going to be executed repeatedly, repl on slow android device https://gist.github.com/rasom/b6a154bef04894c3d5ecff5fca6fbfcf

Copy link
Member Author

Choose a reason for hiding this comment

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

Eric, 10000000 times, really? :)

Copy link
Contributor

Choose a reason for hiding this comment

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

A docstring explaining why you use theses steps would be better than renaming the numbers 5 11 16 and 20

Copy link
Contributor

Choose a reason for hiding this comment

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

It's only magic numbers if there is no explanation

Copy link
Member Author

Choose a reason for hiding this comment

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

I disagree, because numbers are co-dependent. And as optimization this change improves nothing.

Copy link
Contributor

@yenda yenda May 20, 2019

Choose a reason for hiding this comment

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

Would that work for you then?

(def ^:const first-step 5)
(def ^:const second-step 11) 
(def ^:const third-step 16)
(def ^:const step-increment 20)

(defn increment-limit [lim]
(case lim
     first-step second-step
     second-step third-step
     (+ lim step-increment)))

Works because the steps are defined as constants and the compiler will replace them by the int

I would still like to understand why the increments are +6 then +4 then +20, looks like the real magic numbers here

Copy link
Member Author

Choose a reason for hiding this comment

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

I would still like to understand why the increments are +6 then +4 then +20, looks like the real magic numbers here

At first, it is 5, then +6, then +11. Not +6 then +4 then +20.

And... well that's true, they are magic numbers (but not in terms of programming), and as I'm 99% sure we are going to change these numbers I prefer to code the relations between them.

The way how I "inferred" those numbers: on a slower device (samsung a500d, 720 x 1280 pixels, 16:9 ratio (~294 ppi density)) I opened #status and #status-core chats during several days, and almost always not more than 5 messages were shown initially. 11 is the max number of messages which fits on that screen. Both number are device specific, and probably can be derived more precisely in some better way, but 11 is kind of a safe number for almost all devices, chances that more than 11 messages will be shown on the initial screen in a regular chat are quite low at the moment.



@annadanchenko annadanchenko moved this from REVIEW to E2E Tests in Pipeline for QA May 21, 2019
@Serhy Serhy moved this from E2E Tests to TO TEST in Pipeline for QA May 21, 2019
@Serhy Serhy self-assigned this May 21, 2019
@Serhy Serhy moved this from TO TEST to IN TESTING in Pipeline for QA May 21, 2019
@Serhy
Copy link
Contributor

Serhy commented May 21, 2019

Great, @rasom, no regressions and improved performance when navigating to chat with messages.
Improvement perfectly visible especially when open chat screen with 20+ messages required "heavy"
text parsing:
Results for 'Galaxy Note 4' when navigating from "Chats" to the chat that has 20 messages with content *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold*:

  • with limit 9.5s
  • without limit 5.3s -> 55% faster

@rasom could you please remove code required for testing, we'll do smoke test of new builds and then merge.

@rasom
Copy link
Member Author

rasom commented May 21, 2019

@Serhy "without limit" (check it when transition is ended) is actually the old version. So if it is faster, then there is no improvement.

@Serhy
Copy link
Contributor

Serhy commented May 21, 2019

@Serhy "without limit" (check it when transition is ended) is actually the old version. So if it is faster, then there is no improvement.

Sorry, misplaced the values above:
The time it takes from tap on Chats screen upon chat with 20 messages till the messages appear

  • when no limit applied: 9.5s
  • with limit (when 5 messages rendered firstly): 5.3s

@rasom
Copy link
Member Author

rasom commented May 21, 2019

@Serhy that sounds better, I hope it is so :D

@mandrigin
Copy link
Contributor

Wait, that is the whole payload that can make the app choke? *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold* *bold*

@mandrigin
Copy link
Contributor

mandrigin commented May 21, 2019

And that's 9.5 seconds for 20 messages?

@rasom
Copy link
Member Author

rasom commented May 21, 2019

And that's 9.5 seconds for 20 messages?

that's not exactly a problem which this pr targeted, but that's definitely something we must fix

@yenda
Copy link
Contributor

yenda commented May 21, 2019

@mandrigin @rasom we should store the messages as a tree of element based to avoid having to do any parsing at runtime, that is why I suggested Jan to do but he insisted on storing the rendering info separately which can be quite expensive in some cases. And since we already store the raw payload anyway we can always use it in case we do some migrations on rendering info

@mandrigin
Copy link
Contributor

I will create a separate issue for that

@rasom
Copy link
Member Author

rasom commented May 21, 2019

@yenda do you mean we parse that data each time messages are rendered? If not, the way how we store data doesn't matter.

@yenda
Copy link
Contributor

yenda commented May 21, 2019

@rasom afaik we parse them once to build up this kind of index that says where to cut the file to build a tree of elements when rendering, I think we should store this tree of elements in edn instead so that we only have to render

@rasom rasom force-pushed the experement-limit-rendered-messages branch from d1d5eea to 7b5f19a Compare May 22, 2019 06:22
@rasom rasom requested a review from a team as a code owner May 22, 2019 06:22
@rasom
Copy link
Member Author

rasom commented May 22, 2019

could you please remove code required for testing, we'll do smoke test of new builds and then merge.

@Serhy done

@statustestbot
Copy link

100% of end-end tests have passed

Total executed tests: 49
Failed tests: 0
Passed tests: 49

Passed tests (49)

Click to expand
1. test_block_user_from_public_chat
Device sessions

2. test_filters_from_daap
Device sessions

3. test_copy_and_paste_messages
Device sessions

4. test_send_transaction_from_daap
Device sessions

5. test_request_and_receive_tokens_in_1_1_chat
Device sessions

6. test_deploy_contract_from_daap
Device sessions

7. test_open_transaction_on_etherscan
Device sessions

8. test_public_chat_messaging
Device sessions

9. test_long_press_to_delete_1_1_chat
Device sessions

10. test_password_in_logcat_sign_in
Device sessions

11. test_text_message_1_1_chat
Device sessions

12. test_add_to_contacts
Device sessions

13. test_sign_typed_message (TestRail link is not found)
Device sessions

14. test_unread_messages_counter_1_1_chat
Device sessions

15. test_logcat_send_transaction_from_daap
Device sessions

16. test_send_message_in_group_chat
Device sessions

17. test_logcat_send_transaction_from_wallet
Device sessions

18. test_send_token_with_7_decimals
Device sessions

19. test_modify_transaction_fee_values
Device sessions

20. test_send_eth_from_wallet_to_address
Device sessions

21. test_manage_assets
Device sessions

22. test_logcat_send_transaction_in_1_1_chat
Device sessions

23. test_request_and_receive_eth_in_1_1_chat
Device sessions

24. test_long_press_to_delete_public_chat
Device sessions

25. test_send_emoji
Device sessions

26. test_search_chat_on_home
Device sessions

27. test_logcat_recovering_account
Device sessions

28. test_messaging_in_different_networks
Device sessions

29. test_send_tokens_in_1_1_chat
Device sessions

30. test_network_mismatch_for_send_request_commands
Device sessions

31. test_logcat_sign_message_from_daap
Device sessions

32. test_switch_users_and_add_new_account
Device sessions

33. test_send_stt_from_wallet
Device sessions

34. test_send_eth_in_1_1_chat
Device sessions

35. test_login_with_new_account
Device sessions

36. test_send_eth_from_wallet_to_contact
Device sessions

37. test_add_contact_from_public_chat
Device sessions

38. test_send_two_transactions_one_after_another_in_dapp
Device sessions

39. test_password_in_logcat_creating_account
Device sessions

40. test_backup_recovery_phrase
Device sessions

41. test_offline_status
Device sessions

42. test_open_google_com_via_open_dapp
Device sessions

43. test_unread_messages_counter_public_chat
Device sessions

44. test_sign_message_from_daap
Device sessions

45. test_user_can_remove_profile_picture
Device sessions

46. test_share_contact_code_and_wallet_address
Device sessions

47. test_request_eth_in_wallet
Device sessions

48. test_refresh_button_browsing_app_webview
Device sessions

49. test_backup_recovery_phrase_warning_from_wallet
Device sessions

@Serhy
Copy link
Contributor

Serhy commented May 22, 2019

I don't see any regressions with Android 6.0.1, Android 8.1, iOS 12.2, MacOS builds.
When chat view with 5+ messages in history opened - the first 5 messages is rendered, then next bunch of messages appear.

@Serhy Serhy moved this from IN TESTING to MERGE in Pipeline for QA May 22, 2019
@rasom rasom force-pushed the experement-limit-rendered-messages branch from 7b5f19a to 932ef27 Compare May 22, 2019 13:59
@rasom rasom merged commit 932ef27 into develop May 22, 2019
Pipeline for QA automation moved this from MERGE to DONE May 22, 2019
@delete-merged-branch delete-merged-branch bot deleted the experement-limit-rendered-messages branch May 22, 2019 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

7 participants