Skip to content

Conversation

@youknowriad
Copy link
Contributor

This PR builds on top of #11899 And it's another refactoring to the BlockListBlock component to avoid useless selectors.

In my testing. Key press events are 22% faster in long posts.

@youknowriad youknowriad added the [Type] Performance Related to performance efforts label Nov 28, 2018
@youknowriad youknowriad self-assigned this Nov 28, 2018
@youknowriad youknowriad requested review from a team, aduth and sgomes November 28, 2018 10:23
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we're using strings now for RichText values, the isEqual is useless I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

=== will check that the values are of the same type and that their values match, so it'll work nicely in the context of two strings, yes.

Copy link
Member

Choose a reason for hiding this comment

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

Since we're using strings now for RichText values, the isEqual is useless I think.

I also don't think it's something we should have ever wanted, even for non-primitive types, since even if the values are deeply equal, the test seems like it should be more concerned about whether the value has ever changed from its default-assigned reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the value has ever changed from its default-assigned reference.

The reason was: you type in a paragraph, you backspace, you click outside of the block. You have an empty paragraph but a new reference.

Copy link
Member

Choose a reason for hiding this comment

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

And to me I'd be fine to call that "modified" 🤷‍♂️

@mtias mtias added this to the 4.7 milestone Nov 28, 2018
Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed here #11899 (comment) this means we now show the inserter even if the previous block is empty.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice removal! Should be an excellent improvement not to load two blocks every single time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Internal filter not useful anymore because we got rid of "layout" attributes.

Copy link
Contributor

@sgomes sgomes left a comment

Choose a reason for hiding this comment

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

The code changes look good to me. Great work, @youknowriad! This is an excellent example of where a small UX compromise can lead to a big performance boost.

I'll try to replicate your results in the meantime, but code-wise looks good to merge 👍

@sgomes
Copy link
Contributor

sgomes commented Nov 28, 2018

I see a similar improvement (23%) in my machine 👍

@youknowriad youknowriad force-pushed the perf/avoid-previous-block-selector branch from 849c449 to c3987ff Compare November 28, 2018 12:41
Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

I like this in an effort of reducing the unpredictability around when and where a sibling inserter is shown. One thing I might worry about is: Before we'd never shown a sibling inserter around an empty default block at all, and now we show it after but not before an empty default block. It seems to me we'd probably be better off one way or the other. In other words, do we even need this canShowInBetweenInserter at all ?

Copy link
Member

Choose a reason for hiding this comment

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

Since we're using strings now for RichText values, the isEqual is useless I think.

I also don't think it's something we should have ever wanted, even for non-primitive types, since even if the values are deeply equal, the test seems like it should be more concerned about whether the value has ever changed from its default-assigned reference.

const { clientId, previousBlockClientId, nextBlockClientId, onMerge } = this.props;

const { clientId, getPreviousBlockClientId, getNextBlockClientId, onMerge } = this.props;
const previousBlockClientId = getPreviousBlockClientId( clientId );
Copy link
Member

Choose a reason for hiding this comment

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

Another thing which will be nice to move to the dispatch handler when #11851 lands. Or, at least, our non-conventional use of selectors as functions directly within the component is concerning (but largely in its being unconventional).

Copy link
Member

Choose a reason for hiding this comment

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

Or, at least, our non-conventional use of selectors as functions directly within the component is concerning (but largely in its being unconventional).

On further reflection, I think I could articulate my concern better in being a diminished distinction between withSelect as serving to provide data and withDispatch as serving to provide behavior, where what we've done here is more in the realm of a behavior.

To clarify, not something which needs to be addressed here.

isSelected,
isParentOfSelectedBlock,

// We only care about this value when the shift key is pressed.
Copy link
Member

Choose a reason for hiding this comment

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

This comment is no longer strictly applicable to the use-case, since there's now a second use-case.


return every( attributeKeys, ( key ) =>
isEqual( newDefaultBlock.attributes[ key ], block.attributes[ key ] )
return every( blockType.attributes, ( value, key ) =>
Copy link
Member

Choose a reason for hiding this comment

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

There's a subtlety here in how we use the block type's attributes definition instead of the actual default block we've created; I assume that's so we account for keys which don't have a default assigned and thus would be absent from the default block, but potentially present in the block being tested?

Some comment to this effect could help clarify for future maintainers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My thinking is that the previous implementation was needed because undeclared attributes were persisted initially, but that's not the case anymore.

return false;
}

const newDefaultBlock = createBlock( defaultBlockName );
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a red herring, but createBlock seems like something which in its current state is somewhat non-trivial, at least if we expect it to be called frequently. Do we need to create a new instance of the block each time this function is called?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need the "normalized" attributes (default values), An alternative would be to avoid this behavior "isUnmodified" if the default block has been changed. And just rely on very quick but static checks as we know the block is "paragraph".

@youknowriad
Copy link
Contributor Author

In other words, do we even need this canShowInBetweenInserter at all ?

I don't know, I'll explore it separately :)

@youknowriad
Copy link
Contributor Author

or actually, I'll update this PR iff it seems useless.

@aduth
Copy link
Member

aduth commented Nov 28, 2018

In other words, do we even need this canShowInBetweenInserter at all ?

I don't know, I'll explore it separately :)

or actually, I'll update this PR iff it seems useless.

My worry is that the pull request in its current form is the worst of all options, between:

  • Sibling inserter shown neither before nor after an empty block (master)
  • Sibling inserter shown after, but not before an empty block (this branch in its current incarnation)
  • Sibling inserter shown before and after an empty block

@youknowriad
Copy link
Contributor Author

I pushed a commit to always show the in-between inserter.

@aduth
Copy link
Member

aduth commented Nov 28, 2018

I pushed a commit to always show the in-between inserter.

FYI @jasmussen

@aduth
Copy link
Member

aduth commented Nov 28, 2018

The insertion point line is not shown when hovering a block option in the inserter before an empty block. Am I correct in assuming that this would be resolved by #12384 ?

point

@youknowriad
Copy link
Contributor Author

I think that's correct @aduth

now that you mention that, I think I know why we don't show the inserter and the insertion point for empty blocks, that's because we replace them instead of adding new blocks when you choose a block from the inserter.

I personally think it's a fine "compromise" for performance to show them even if we replace the block instead of inserting new ones.

@aduth
Copy link
Member

aduth commented Nov 28, 2018

that's because we replace them instead of adding new blocks when you choose a block from the inserter.

I find that a bit peculiar as well 😆 But it's neither here nor there, as I don't really find this to really have an effect (negative or positive) on the expectation of that behavior.

@mtias mtias added the [Feature] Inserter The main way to insert blocks using the + button in the editing interface label Nov 28, 2018
@youknowriad youknowriad merged this pull request into update/avoid-get-block-block-component Nov 30, 2018
@youknowriad youknowriad deleted the perf/avoid-previous-block-selector branch November 30, 2018 08:15
@mtias
Copy link
Member

mtias commented Nov 30, 2018

Nice to see this improvement!

youknowriad added a commit that referenced this pull request Nov 30, 2018
* Avoid rerending the current block if the previous block change

* Always show the sibling inserter

* Optimize the insertion point component (#12384)
youknowriad added a commit that referenced this pull request Nov 30, 2018
* Avoid getBlock in block-list/block

* Update data docs

* Fix unit tests post rebase :)

* Rename props

* Clarify the filter position

* Avoid repeating the selector dependants

* Fix small typo in the docs

* Avoid rerending the current block if the previous block change (#12379)

* Avoid rerending the current block if the previous block change

* Always show the sibling inserter

* Optimize the insertion point component (#12384)

* Fix lock file

* Fix linting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Inserter The main way to insert blocks using the + button in the editing interface [Type] Performance Related to performance efforts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants