TextInput becomes slow after lots of typing
See original GitHub issueEnvironment
$ react-native info
Environment:
OS: Linux 4.9
Node: 8.11.3
Yarn: 1.7.0
npm: 5.6.0
Watchman: Not Found
Xcode: N/A
Android Studio: Not Found
Packages: (wanted => installed)
react: 16.3.1 => 16.3.1
react-native: 0.56.0 => 0.56.0 (*)
(*) In my test app, actually v0.55.4 plus the patch from #19645 . Others on #19126 report the same symptoms using v0.56.
Description
After typing a lot of text into a controlled TextInput, like ~500 char on a recent fast phone, we start dropping frames. It gets worse the more you type; at ~1000 char, we very frequently drop frames and the app looks noticeably laggy.
Reproducible Demo
The original repro is by @s-nel: https://github.com/s-nel/rn19126
Originally reported at https://github.com/facebook/react-native/issues/19126#issuecomment-402904164; more discussion in subsequent comments in that thread.
In particular, here’s the video from that repro:
Here’s a video by @s-nel on my test app, with this description:
Yes I can reproduce from [that repo] after typing for a couple minutes straight. I don’t have to clear anything as the original bug description [in #19126] indicates. Here you can see my JS framerate drop to single digits from adding a few characters
Here’s my description of replicating that repro, again in my test app:
I just tried again with my test app, on RN 0.55.4 + patch. If I type continuously for about 60 seconds – maybe 400-500 characters, at a rough estimate (just gibberish, both thumbs constantly typing letters) – then the perf overlay gets to about “10 dropped so far”, and zero stutters. If I continue and get up to about 90 seconds, the “dropped” figure climbs faster, and the framerate (in “JS: __ fps”) noticeably drops. At about 150 seconds (~1000 characters?), the “dropped” figure rapidly climbs past 200, and the framerate hangs out around 30.
Even at that point, it’s still “0 stutters”. And if I ignore the perf overlay and try typing normal text and watching it like I were using an app for real: it’s a bit laggy, but doesn’t make things feel unusable or outright broken, and I think most of the time I wouldn’t even notice.
That was on a Pixel 2 XL; the numbers will probably vary with hardware.
Background from previous bug
This bug seems closely related to #19126; the repro steps and symptoms seem to be exactly the same, except quantitatively much less severe. (The original reports of #19126 describe clearing the input as part of the repro; I now think that was probably a red herring.)
The extreme symptoms of #19126 were absent in v0.54, introduced in v0.55, and fixed in v0.56 by #19645 . As I wrote when I figured out the cause of that (leading to the one-line fix in #19645):
[This buggy NaN comparison] means every text shadow node will create a
CustomLetterSpacingSpan
around its contents, even when theletterSpacing
prop was never set. It must be that we’re somehow ending up with large numbers of these shadow nodes – that sounds like a bug in itself, but I guess it’s normally low-impact – and this condition is failing to prune them from causing a bunch of work here.
I think we’re now looking at exactly that underlying bug. It may well have been present in v0.54 and earlier releases; I don’t think we have any data on that. [EDIT: @piotrpazola finds below that the bug is present in v0.50, and absent in v0.49.]
I don’t know anything more about what causes it; even the hypothesis that we’re ending up with large numbers of text shadow nodes is just an inference from how it interacts with the line fixed in #19645. So, more debugging is required.
I don’t expect to do that debugging myself, because these remaining symptoms are no longer one of the top issues in our own app. But I hope somebody else will!
Issue Analytics
- State:
- Created 5 years ago
- Reactions:61
- Comments:84 (4 by maintainers)
Updated labels and flagged this as a high priority. Hopefully we can get this fixed as soon as possible.
I think closing this is a little premature. This is a major issue that has affected the entire user base for several years. This issue alone has caused several developers i know personally to abandon react native due to frustration and hundreds of hours of lost productivity. I think it deserves some more thorough testing. And if it is fixed, maybe we can find the commit that fixed it and the reason it was broken in case it turns up again in the future.