bonafideduck / react-highlight-within-textarea

React component for highlighting bits of text within a textarea
93 stars 13 forks source link

Long text performance #175

Closed standbyoneself closed 1 year ago

standbyoneself commented 1 year ago

Hi there. Thank you for this library, it's really helpful.

But there is a performance issue because rerender is caused on every change event. It's a little bit annoying because our customers have to work with long text up to 50000 length. Codesandbox: https://codesandbox.io/s/rhwta-string-forked-ngelzp?file=/src/App.js

If we are using native draft.js, it would rerender only span where change is happened.

Any plans on optimizing it? Maybe some tips or workarounds?

bonafideduck commented 1 year ago

I’ll have to think if there are ways to optimize this. When I created it, my need was for short forms. I have to balance this against a v3 conversion to quill since draft is end of life.

Do you typically use ranges, or was that just for testing purpose?

standbyoneself commented 1 year ago

We are really using ranges. We need to parse the boolean search query, build AST, grab the start/end positions of operators (AND, OR, NOT), not operands (WORD, PHRASE) and highlight those operators. Example of boolean search query: "github OR gitlab AND NOT bitbucket". Length of it may be few thousands symbols.

bonafideduck commented 1 year ago

@standbyoneself , I believe I have a performance fix. Would you be willing to test a preview? The branch is issue-175. In your project, you should be able to:

cd node_modules
rm -rf react-highlight-within-textarea
git clone -b issue-175 https://github.com/bonafideduck/react-highlight-within-textarea.git
cd react-highlight-within-textarea
yarn
yarn build

There may be some console logs in there. I'm still cleaning up.

bonafideduck commented 1 year ago

Also you can:

yarn start
open http://localhost:3000/performance

to see a hidden demo.

standbyoneself commented 1 year ago

@bonafideduck thanks for a reply. I have tested it locally with CPU throttling 6x on my MacBook Pro M1 Pro. In the first example input I have copy-paste your phrase "Potato potato tomato potato." in order to retrieve string up to 7000 length. After that I am trying to input "1", and it tooks approximately 150ms via React Profiler, which is 3x much faster than in the main branch (435ms), but still is not enough since the text length may be 50000. I have noticed that you rerender only the block that have been changed, but we need to inspect via DevTools why it tooks 150 ms for inserting one symbol

bonafideduck commented 1 year ago

@standbyoneself , I did an experiment with raw draftjs in DraftPerf.tsx and unfortunately, that was only around 30% faster. I was getting 283ms-497ms with my code and 202ms-375ms with raw draftjs. So I'm running into diminishing returns on what I can do without trying to replace draft with quill (which would be version 4.0 of this code).

standbyoneself commented 1 year ago

@bonafideduck I understood. Do you have any approximate dates on releasing this useful library used quill.js?

bonafideduck commented 1 year ago

Unfortunately, it is no time soon. I also don’t know if quill would be any more efficient. If all you need to do is highlight certain words, you might consider using quill directly.

standbyoneself commented 1 year ago

Okay, I'll follow your projects.

bonafideduck commented 1 year ago

@standbyoneself , I have determined that quill will not be more performant than what is already available. In fact it will be worse. Check out this demo for this code.

bonafideduck commented 1 year ago

Also, the draftPerformance seems to be pretty snappy when not debugging.