Extremely bad performance on scytale site
Categories
(Core :: DOM: Core & HTML, defect, P2)
Tracking
()
Tracking | Status | |
---|---|---|
firefox67 | --- | affected |
People
(Reporter: bzbarsky, Unassigned)
References
(Depends on 3 open bugs, )
Details
STEPS TO REPRODUCE:
- Load https://www.cryptool.org/en/cto-ciphers/scytale
- Try typing quickly in the "Plaintext" textarea.
EXPECTED RESULTS: Typing works, cyphertext appears in the "Encrypted text" textarea and the "Rendering" space.
ACTUAL RESULTS: Typing is very laggy, browser starts freezing up.
I did a profile, and we're spending tons of time notifying ranges during various editor and DOM operations.
I then added logging to the nsRange constructor and destructor, and every keypress in the "Plaintext" textarea allocates about 6700 ranges. That includes things like arrow keys. The ranges are deallocated fairly quickly, but definitely async; when typing I can easily get to a state where there are 150k+ live ranges.
I'm still investigating why all these ranges get allocated, but wanted to get this on file just in case.
Comment 2•5 years ago
|
||
FWIW, it is rather janky on Chrome too.
Reporter | ||
Comment 3•5 years ago
|
||
So a few things going on here:
- On every keyup on the plaintext, the site re-encrypts the plaintext. That leads to a bunch of
.value += stuff
calls on the "Rendering" textarea, like so:
document.getElementById("railfence-display").value = "";
for (var f = 0; f < p.length; f++) {
document.getElementById("railfence-display").value += "| ";
for (var u = 0; u < h; u++) document.getElementById("railfence-display").value += p[f].charAt(u) + " | ";
document.getElementById("railfence-display").value += "\n"
}
That looks like one value set per char of text, plus two value sets per line of rendering plus one overall set to ""
. For the default text, we have 35 chars and three lines (until we start typing), so that means 42 value sets. As we type, it should get worse.
-
Every
.value +=
call ends up doingTextEditor::SetText
which callsTextEditor::SetTextAsSubAction
which doesEditorBase::SelectEntireDocument
which doesSelection::Extend
, which callsnsRange::CloneRange
. That's one range created. -
Selection::Extend
also directly constructs a range fordifRange
. -
TextEditor::SetText
then doesTextEditor::SetTextAsSubAction
->TextEditor::ReplaceSelectionAsSubAction
-> ... ->TextEditor::DeleteSelectionWithTransaction
->DeleteRangeTransaction::DeleteRangeTransaction
which clones another range. -
Still continuing with the "delete selection" thing, we land in
DeleteRangeTransaction::DoTransaction
which callsSelection::Collapse
, which creates another range.
OK, so that's 4 ranges, 42 value sets = 168 ranges. That's not 6000...
I guess the Selection::Extend issues are largely tracked by bug 1367744. The Selection::Collapse bit is bug 1365874.
Anyway, I actually measured how many .value
sets happen on every keypress, and it's 1716, not 42. That matches the number of ranges I see created (1716 * 4 = 6864), but I don't quite understand why there are so many yet.
Reporter | ||
Comment 4•5 years ago
|
||
I don't see much jank here in Chrome, fwiw. Certainly nothing like us (complete with slow script dialogs).
Reporter | ||
Comment 5•5 years ago
|
||
Oh, the relevant JS file, by the way, is https://www.cryptool.org/_ctoApps/skytale/skytale-de.js. Which is of course minified.
Reporter | ||
Comment 6•5 years ago
|
||
Oh, I see. Each keypress does one call to process() but then each call to process() does a bunch of encrypt() calls. In fact it seems to do one call per character of cyphertext or so (!). In this case that's 35 calls. 35 * 42 = 1470, which is still not 1716, but at least approaching the right ballpark...
OK, so the site is pretty buggy, but our handling of it is still terrible. :(
Reporter | ||
Comment 7•5 years ago
|
||
I tried to send a note to the website about the O(N^2) behavior. We'll see whether they fix that...
Comment 8•5 years ago
|
||
Selection::Extend issues are largely tracked by bug 1367744
Yeah, but I guess Selection::Extend()
cannot be so fast since it requires to compare DOM points a lot. Therefore, as far as possible, we shouldn't use it in our code.
Updated•5 years ago
|
Assignee | ||
Updated•5 years ago
|
Comment 9•5 years ago
|
||
I avoided calling Selection::Extend()
internally in most cases by fixing bug 1533293. How about the result? If it's not enough, I'll investigate TextEditor::DeleteSelectionWithTransaction()
and DeleteRangeTransaction::DeleteRangeTransaction
.
Reporter | ||
Comment 10•5 years ago
|
||
I should probably wait until bug 1533293 relands...
Reporter | ||
Comment 11•5 years ago
|
||
Just retested with bug 1533293 and things are not noticeably better...
The profile is at http://bit.ly/2FzppLA
One interesting thing I see in there is a bunch of time spent messing with the clipboard on every value set, afaict. See this stack: http://bit.ly/2Fw9Yny
Comment 12•5 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #11)
Just retested with bug 1533293 and things are not noticeably better...
The profile is at http://bit.ly/2FzppLA
Well, I need to work on DeleteRangeTransaction::DoTransaction()
... And also, looks like that nsRange::SetSelection()
is too expensive even though it's called when adding new range to a Selection
.
One interesting thing I see in there is a bunch of time spent messing with the clipboard on every value set, afaict. See this stack: http://bit.ly/2Fw9Yny
Reporter | ||
Comment 13•5 years ago
|
||
Maybe we can keep track of whether the selection was already empty?
Comment 14•5 years ago
|
||
(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #13)
Maybe we can keep track of whether the selection was already empty?
No idea because selection change notifications may be batched.
Comment 15•5 years ago
|
||
Oh, I realized that setting <textarea>.value
wasn't optimized by bug 1358025. Looks like that I can do it without big patch.
Comment 16•5 years ago
|
||
According to http://bit.ly/2FzppLA, it spent in SetTextAsSubAction()
29% of the period but it's a slow path to setting new value from JS. Now, bug 1548751 is fixed, so, most of the time is saved by using the fast path.
Comment 17•5 years ago
|
||
Under editor, most time spends in mozilla::dom::CharacterData::SetData()
and mozilla::dom::Selection::Collapse()
. I think that Editor should save touching Selection in the future, but I have no idea for the former issue.
Updated•2 years ago
|
Comment 18•1 year ago
|
||
I guess the site is now https://www.cryptool.org/en/cto/scytale ?
That is about equally bad in all the browsers. Chrome is perhaps worse and Safari keep queuing key events so that even after typing
they keep coming in for seconds.
https://share.firefox.dev/3WWvXdF
Flattening JS rope is taking quite a bit time, among other things
Description
•