Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

[MM-37048] Do not save drafts until typing has stopped for X milliseconds #8396

Merged
merged 4 commits into from
Jul 15, 2021

Conversation

jwilander
Copy link
Member

@jwilander jwilander commented Jul 13, 2021

Summary

Currently, we were saving drafts for messages being typed into the post and comment textboxes on animation frames which can occur quite frequently. Saving drafts also seems to be less performant on some browser/OS/device combinations than on others. They also fire off a number of dispatches and change redux state which can negatively impact performance too. During some local testing, where I added a console log for each draft save, I was seeing it saved on every single key press which is 1) saving significantly more often than necessary and 2) could be negatively impacting performance, particularly in certain environments.

This is after typing about 100 characters into the post textbox:
Screen Shot 2021-07-13 at 8 28 02 AM

In addition some very useful profiles from the community on Firefox are showing saveDraftFrame being called about every 100ms during typing and was taking up the majority of the JS processing time in the profile:
Screen Shot 2021-07-12 at 1 43 29 PM

This PR moves from using animation frames to save the draft to a more controlled setTimeout which will only save the draft after 500ms of no typing has occurred (or the component unmounts).

Release Note

Improve typing performance in affected environments by reducing the frequency at which drafts are saved

Ticket link: https://mattermost.atlassian.net/browse/MM-37048

@jwilander jwilander added 2: Dev Review Requires review by a core commiter 3: QA Review Requires review by a QA tester labels Jul 13, 2021
@@ -46,6 +48,8 @@ import MessageSubmitError from 'components/message_submit_error';

const KeyCodes = Constants.KeyCodes;

const CreatePostDraftTimeoutMilliseconds = 500;
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 initially started lower at 250ms but during my testing it would still fire when I was typing at my normal speed. At 500ms it would consistently only fire after I had a significant pause in my typing.

@hmhealey I know you wanted to lean on the lower end but for this to have the performance impact I'm hoping it will I think it's important that saving doesn't occur during typing.

Copy link
Member

Choose a reason for hiding this comment

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

@jwilander Non-blocking, but is there any benefit to having this constant declared here and the same one declared in create_comment. Is there any point where we'd want those intervals to be different? If not it might be worth be putting the constant in a constants file.

Copy link
Member

Choose a reason for hiding this comment

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

I was originally thinking we could lean on the side of having it fire periodically as the user was typing, but I guess if saving the draft is taking as long as we've seen, you're probably right that it's better to be on the safe side with this. If we hear people are losing drafts, we can always back off on the interval.

As for the duplicated constants, I don't think it's important enough to move to the constants file. That thing is bloated with a lot of things that are only used in one or two places if they're even still used at all. I think having two values is fine since I can't see us using this anywhere else, and ideally, both the CreatePost and CreateComment would be rewritten to share this logic entirely anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

As for the duplicated constants, I don't think it's important enough to move to the constants file. That thing is bloated with a lot of things that are only used in one or two places if they're even still used at all. I think having two values is fine since I can't see us using this anywhere else, and ideally, both the CreatePost and CreateComment would be rewritten to share this logic entirely anyway.

This was pretty much my exact reasoning.

@jwilander jwilander added the Setup Cloud Test Server Setup a test server using Mattermost Cloud label Jul 13, 2021
@jwilander
Copy link
Member Author

@jgilliam17 can you test to make sure that post and comment drafts are still saved correctly?

@jwilander jwilander added the Do Not Merge Should not be merged until this label is removed label Jul 13, 2021
@jwilander
Copy link
Member Author

Found a minor issue with the comment button staying disabled too long that might be related to this change. Going to investigate that

@jwilander jwilander added Work in Progress Not yet ready for review and removed 2: Dev Review Requires review by a core commiter 3: QA Review Requires review by a QA tester labels Jul 13, 2021
@jwilander
Copy link
Member Author

Fixed the issues. @jgilliam17 can you smoke test commenting on posts/threads with this change too?

@jwilander jwilander added 2: Dev Review Requires review by a core commiter 3: QA Review Requires review by a QA tester and removed Do Not Merge Should not be merged until this label is removed Work in Progress Not yet ready for review labels Jul 13, 2021
@jwilander
Copy link
Member Author

Also @jgilliam17 (and anyone else) please leave the test server up since I'm going to ask some people to create accounts and see if improves performance for them

@jgilliam17
Copy link
Contributor

@jwilander Do we have a Jira ticket for this?

@jwilander
Copy link
Member Author

No, I didn't create one since it was a bit reactionary. I can create one if you want, though.

@jgilliam17
Copy link
Contributor

I'll add one as a reminded to test again after merge. 🙂

@jgilliam17 jgilliam17 changed the title Do not save drafts until typing has stopped for X milliseconds [MM-37048] Do not save drafts until typing has stopped for X milliseconds Jul 13, 2021
@@ -1,6 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

/* eslint-disable max-lines */
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated, but we should really get rid of this...it's more annoying than it helps.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we could increase the limit or disable it for older files, but I'd like to keep it for newer files since it's nice to discourage people from adding new files with too much stuff going on in them. Only 1/5 on that though.

Copy link
Member

@hmhealey hmhealey left a comment

Choose a reason for hiding this comment

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

This looks good to me. I was thinking we might use lodash's debounce utility since that avoids having to manage the timeout manually, but the more I think about it, doing that manually has me less concerned about potentially making mistakes like saving a draft to the wrong channel.

@hmhealey hmhealey removed the 2: Dev Review Requires review by a core commiter label Jul 14, 2021
Copy link
Contributor

@jgilliam17 jgilliam17 left a comment

Choose a reason for hiding this comment

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

Thanks @jwilander
Tested, looks good to merge.

  • Verified post and comment drafts are saved correctly, no issues commenting on threads and single posts.

@jgilliam17 jgilliam17 added 4: Reviews Complete All reviewers have approved the pull request and removed 3: QA Review Requires review by a QA tester labels Jul 15, 2021
@jwilander jwilander merged commit 95597ba into master Jul 15, 2021
@jwilander jwilander deleted the draft-saving branch July 15, 2021 14:55
@mattermod mattermod removed the Setup Cloud Test Server Setup a test server using Mattermost Cloud label Jul 15, 2021
@mm-cloud-bot
Copy link

Test server destroyed

1 similar comment
@mm-cloud-bot
Copy link

Test server destroyed

jwilander added a commit that referenced this pull request Jul 23, 2021
…onds (#8396)

* Do not save drafts until typing has stopped for X milliseconds

* Fix comment box relying on draft stored in redux

* Fix tests

* Fix another test
jwilander added a commit that referenced this pull request Jul 23, 2021
…onds (#8396)

* Do not save drafts until typing has stopped for X milliseconds

* Fix comment box relying on draft stored in redux

* Fix tests

* Fix another test
jwilander added a commit that referenced this pull request Jul 23, 2021
* [MM-37048] Do not save drafts until typing has stopped for X milliseconds (#8396)

* Do not save drafts until typing has stopped for X milliseconds

* Fix comment box relying on draft stored in redux

* Fix tests

* Fix another test

* MM-37048 Temporarily store drafts in localStorage and rehydrate manually to fix persistence issues (#8411)

* Temporarily store drafts in localStorage and rehydrate manually to fix persistence issues

* Fix console error on reload immediately after typing

* Null out saveDraftFrame to prevent potential double saves

* Fix draft removal on create_comment and unload in create_post (#8428)
jwilander added a commit that referenced this pull request Jul 23, 2021
* [MM-37048] Do not save drafts until typing has stopped for X milliseconds (#8396)

* Do not save drafts until typing has stopped for X milliseconds

* Fix comment box relying on draft stored in redux

* Fix tests

* Fix another test

* MM-37048 Temporarily store drafts in localStorage and rehydrate manually to fix persistence issues (#8411)

* Temporarily store drafts in localStorage and rehydrate manually to fix persistence issues

* Fix console error on reload immediately after typing

* Null out saveDraftFrame to prevent potential double saves

* Fix draft removal on create_comment and unload in create_post (#8428)

* Fix style

* Fix test
@amyblais amyblais added Changelog/Done Required changelog entry has been written Docs/Not Needed Does not require documentation labels Jul 30, 2021
@amyblais amyblais added this to the v5.38.0 milestone Jul 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
4: Reviews Complete All reviewers have approved the pull request Changelog/Done Required changelog entry has been written Docs/Not Needed Does not require documentation release-note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants