Specific component for dealing with large amounts of text data (InputTextArea)
SteveSandersonMS opened this issue · 4 comments
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
The issue here is that this a form input that lends itself to large amounts of data. The problem is that people will write things like
<textarea bind="@Value" /> only to find out that when they input a significant amount of text (think of all the editor's out there) will experience bad performance.
The reason is because we will send ALL the data for this input back an forth between the server and the client or even between JS and .NET in the JS side.
We've already had several issues reported about this WRT to it being laggy or leading to to break existing apps in some cases (for example when they exceed the circuit size).
This is not the type of primitive that I expect most people will be successful in authoring, so I think it's worth we help here to make people successful.
Of particular note is the fact that some people will react to issues in their app by raising the SignalR message size limit, which is not something we want to encourage.
What I propose we do here is create an InputTextArea component to deal with this problem using a more sophisticated approach. This might involve breaking the text of the underlying text area into multiple chunks and updating only the chunks that changed, which will drastically reduce the network traffic as well as avoid issues with the message size.
I definitely agree we should fix this.
There are two aspects to the problem:
- Instead of sending just information about the change to the text, we send all of the text on every event. This presents perf issues in Blazor WebAssembly too.
- For Blazor Server specifically, the size of an individual edit (whether it's the whole text, or some new kind of diff) may exceed SignalR message size limits
We may want to address each of these separately. For 1, consider some kind of text diffing system and have it apply to all change/input events, regardless of whether it's from an <input> or a wrapper like <InputText>. For 2, consider a mechanism that splits up all messages that exceed size limits, regardless of whether they are to do with inputs or anything else.
Just going to share some thoughts in case anything triggers an idea.
For the scenario where the bind event is input....
If you know both the char index of the caret in the input and the length of the input before and after the edit then you can work out what happened and deduce what changed in the text.
- Longer: insert the text from old position to new position.
- Shorter: remove text from old position to new position.
- Same: replace text from old index to new
Might be a caveat for pasting from clipboard in overwrite mode to replace part of the original where clipboard content is longer.
If the diff renderer could be given this information as a hint, perhaps you could have a different strategy for sending that component's diff data over SignalR which
- Calculates the new inner content based on the old value + hints.
- If the calculated content is different to the calculated then send all of it.
- If the same then send a specially marked packet which tells the browser what to cut out and what to insert..
PS: New input from user before round-trip might be a problem (perhaps throttle the input?)
For when the bind event is set to when the control loses focus...
You could store up to X of these ordered hints in the UI and sent those to the server instead of the whole new value. But, obviously, only if the hints are smaller than the whole data.
For when the server changes the value...
It might be worth checking the Longest Common Substring algorithm, but only when the string is longer than X characters.