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

[EuiTextTruncate] Performance improvements; Remove non-canvas rendering methods #7210

Merged
merged 16 commits into from
Sep 25, 2023

Conversation

cee-chen
Copy link
Member

@cee-chen cee-chen commented Sep 20, 2023

Summary

Related PRs: #7028 has several heavy performance-related discussions, and #7116 for initial component creation

This PR greatly improves the number of iterations that both DOM and Canvas truncation utils via a fairly simple approach: since we know 1. the available width, and 2. the calculable width of the full text, we can use those two widths to obtain an approximate ratio of characters to slice from the full text. This initial approximately truncated text should be slightly over the available width (due to the added ellipsis), and we can then resume our existing character-by-character removal logic until we detect that the text fits as expected, which should now take <10 iterations.

⚠️ As always, I strongly recommend following along by commit as I tried to separate out misc cleanup preferences/tasks from the main logic (2nd through 4th commit).

See below GitHub thread: This PR, by consensus, also removes DOM rendering completely in favor of canvas-only rendering.

Before

# of character by character iterations:

After

QA

  • text_truncate.spec.tsx passes as before (with no changes)
  • combo_box.spec.tsx truncation tests pass as before with no changes
  • All staging examples should behave the same as production
    • Note: The "Truncation position" example has some minute character differences when at the bounds of including vs omitting the start/end ellipsis. I don't think it's significant enough to warrant deeper investigation, but LMK if you feel otherwise
  • http://eui.elastic.co/pr_7210/#/utilities/text-truncation#performance should feel significantly less laggy than production

General checklist

  • Browser QA
    • Checked in Chrome, Safari, Edge, and Firefox
  • Docs site QA
  • Code quality checklist
  • Release checklist
    • A changelog entry exists and is marked appropriately.
    • Revert [REVERT ME] commit

Prefer `+` concatenation over template literals, just feels easier to read

+ minor naming tweaks
- no longer building text scratch 🎉

- update `middle` to dogfood `startEndAt` function

- use `alternating` logic from `middle` for more granular truncation (was previously truncating 2 chars at a time)
- allow testing greater than 100 lines

+ fix resize observer on load - initial logic is off due to font not yet loading in

- update beta warning - ~100 lines is fairly snappy at this point, and # of characters should no longer be a factor
@cee-chen cee-chen marked this pull request as ready for review September 20, 2023 22:10
@cee-chen cee-chen requested a review from a team as a code owner September 20, 2023 22:10
@cee-chen
Copy link
Member Author

@markov00 @dej611 @tkajtoch As always, I'd greatly appreciate your feedback and any perf testing you feel like doing!

From a preliminary test, Firefox and Chrome/Edge now perform well when resizing 100 lines, even when using DOM rendering (previously was extremely sluggish).

Safari, unfortunately, still feels fairly laggy/choppy on DOM rendering at 100 lines whereas canvas rendering when resizing feels much better.

All browsers started to struggle around 500-1000 instances/usages. Not too sure what we could do there (vs putting the onus on the consumer to use virtualization).

@cee-chen
Copy link
Member Author

Also, if any of you feel like you are a strong yes to either of the two below questions, please let me know!

  1. Is performance still enough of a concern that we should the EuiTextTruncate component to default to canvas rendering instead of DOM rendering?

and

  1. If yes to the above, should we also consider removing TruncationUtilsWithDOM entirely so consumers can't use it?

@dej611
Copy link
Contributor

dej611 commented Sep 21, 2023

Is performance still enough of a concern that we should the EuiTextTruncate component to default to canvas rendering instead of DOM rendering?

To me the DOM implementation made sense only if the Canvas one wasn't available. Given that we have the Canvas one I think performance wise it does not make sense to have the DOM alternative.
I've tested the perf page with all three major browsers and the difference between the two, without virtualisation, are still huge when resizing on my machine (MacBook with M1 Pro).

If yes to the above, should we also consider removing TruncationUtilsWithDOM entirely so consumers can't use it?

To me the precision difference (sub-pixel, which translate to 1 or 2 chars difference at best) won't justify the performance penalty or the cose of manual handling of the virtualization of the wrapper component.

@cee-chen
Copy link
Member Author

cee-chen commented Sep 21, 2023

I've tested the perf page with all three major browsers and the difference between the two, without virtualisation, are still huge when resizing on my machine (MacBook with M1 Pro).

Ahh, that's valid, I keep forgetting I'm on a very fancy M2 now. We could just channel our inner game developers and tell everyone to upgrade their machines (joking, not serious at all :trollface:)

So it sounds like 1 vote for removing the DOM utils entirely, which I'd be down for (re-implementing would be trivial if a consumer did have a request for it in the future, or we could easily suggest a custom implementation).

@tkajtoch, @markov00, any votes from you all for removing DOM utils vs keeping them?

@dej611
Copy link
Contributor

dej611 commented Sep 21, 2023

So it sounds like 1 vote for removing the canvas utils entirely, which I'd be down for (re-implementing would be trivial if a consumer did have a request for it in the future, or we could easily suggest a custom implementation).

You mean removing the DOM utils, right?

@cee-chen
Copy link
Member Author

🤦 Yep, will edit. Sorry, early morning brain

@tkajtoch
Copy link
Member

+1 to canvas rendering being the default and removing DOM utils

@markov00
Copy link
Member

good for me to remove the DOM calculation!

- underlying mechanism is better described in new comment above ratio utils
and make canvas the only rendering method

+ change class inheritance - I'm making canvas text utils its own separate import because there's another component in another PR that will be able to use it soon, that doesn't need truncation logic

+ remove `measurementRenderAPI` prop
+ revert debugging in source code
+ update copy/recommendations
@cee-chen cee-chen changed the title [EuiTextTruncate] Performance improvements [EuiTextTruncate] Performance improvements; Remove non-canvas rendering methods Sep 22, 2023
@kibanamachine
Copy link

Preview staging links for this PR:

@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

History

Copy link
Member

@tkajtoch tkajtoch left a comment

Choose a reason for hiding this comment

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

Thank you for removing DOM utils. The PR looks great!

@cee-chen
Copy link
Member Author

Thanks everyone on this thread for the awesome feedback, recommendations, and advice. Really appreciated!

@cee-chen cee-chen merged commit 020905e into elastic:main Sep 25, 2023
7 checks passed
@cee-chen cee-chen deleted the truncation-ratio branch September 25, 2023 17:22
jbudz pushed a commit to elastic/kibana that referenced this pull request Sep 27, 2023
`v88.3.0`⏩`v88.5.0`

closes #151514

---

## [`88.5.0`](https://github.com/elastic/eui/tree/v88.5.0)

- Updated `EuiCallOut` with a new `onDismiss` prop
([#7156](elastic/eui#7156))
- Added a new `renderCustomToolbar` prop to `EuiDataGrid`, which allows
custom rendering of the toolbar.
([#7190](elastic/eui#7190))
- Added a new `allowResetButton` prop to
`toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows
hiding the "Reset to default" button from the display settings popover.
([#7190](elastic/eui#7190))
- Added a new `additionalDisplaySettings` prop to
`toolbarVisibility.showDisplaySelector` of `EuiDataGrid`, which allows
rendering extra settings inside the display settings popover.
([#7190](elastic/eui#7190))
- Updated `EuiDataGrid`'s toolbar display settings button icon
([#7190](elastic/eui#7190))
- Updated `EuiTextTruncate` with significantly improved iteration
performance. Removed `measurementRenderAPI` prop, as `EuiTextTruncation`
now only uses more performant canvas render API
([#7210](elastic/eui#7210))
- Updated `EuiPopover` with a new configurable `repositionToCrossAxis`
prop ([#7211](elastic/eui#7211))
- Updated `EuiDatePicker` to support `compressed` input styling
([#7218](elastic/eui#7218))
- Added `gradient` and `palette` icon glyphs.
([#7220](elastic/eui#7220))

**Bug fixes**

- Fixed `EuiPopover`'s missing animations on popover close
([#7211](elastic/eui#7211))
- Fixed `EuiInputPopover` anchoring to the wrong side and missing
shadows on smaller screens
([#7211](elastic/eui#7211))
- Fixed `EuiSuperDatePicker` icon spacing on the quick select button
([#7217](elastic/eui#7217))
- Fixed a missing type in `EuiMarkdownEditor`'s default processing
plugins ([#7221](elastic/eui#7221))


## [`88.4.1`](https://github.com/elastic/eui/tree/v88.4.1)

**Bug fixes**

- Fixed missing `className`s on `EuiTextTruncate`
([#7212](elastic/eui#7212))
- Fixed `title`s on `EuiComboBox` dropdown options to always be present
([#7212](elastic/eui#7212))
- Fixed `EuiComboBox` truncation issues when search is an empty space
([#7212](elastic/eui#7212))

## [`88.4.0`](https://github.com/elastic/eui/tree/v88.4.0)

- Updated `EuiComboBox` to allow configuring text truncation behavior
via `truncationProps`. These props can be set on the entire combobox as
well as on on individual dropdown options.
([#7028](elastic/eui#7028))
- Updated `EuiInMemoryTable` with a new `searchFormat` prop (defaults to
`eql`). When setting this prop to `text`, the built-in search bar will
ignore EQL syntax and allow searching for plain strings with special
characters and symbols.
([#7175](elastic/eui#7175))

**Bug fixes**

- `EuiComboBox` now always shows the highlighted search text, even on
truncated text ([#7028](elastic/eui#7028))
- Fixed missing i18n in `EuiSearchBar`'s default placeholder and
aria-label text ([#7175](elastic/eui#7175))
- Fixed the inline compressed styles of `EuiDescriptionListTitle` to use
a taller line-height for readability
([#7185](elastic/eui#7185))
- Fixed `EuiComboBox` to correctly truncate selected items when
displayed as pills and plain text
([#7193](elastic/eui#7193))

**Accessibility**

- Added `aria-current` attribute to `EuiTablePagination`
([#7186](elastic/eui#7186))

**CSS-in-JS conversions**

- Converted `EuiDroppable` and `EuiDraggable` to Emotion; Removed
`$euiDragAndDropSpacing` Sass variables
([#7187](elastic/eui#7187))

---------

Co-authored-by: Patryk Kopycinski <contact@patrykkopycinski.com>
Co-authored-by: Jan Monschke <jan.monschke@elastic.co>
Co-authored-by: Thomas Watson <watson@elastic.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants