Closed Bug 1424901 Opened 7 years ago Closed 6 years ago

Tens of thousands of string copies on Facebook.com

Categories

(Web Compatibility :: Site Reports, defect, P1)

defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: vladan, Unassigned)

References

(Depends on 1 open bug, )

Details

(Keywords: webcompat:needs-diagnosis, Whiteboard: [platform-rel-Facebook] [needsdiagnosis])

I see a ton of duplicate string copies in about:memory for Firefox's web content process after loading facebook.com while logged in. It is easily reproducible. ├─────559,584 B (00.09%) ── string(length=9, copies=23316, "_5zft img")/gc-heap/latin1 ├─────545,192 B (00.09%) -- string(length=24, copies=11815, "Event listenHandler load") │ ├──283,560 B (00.04%) ── gc-heap/latin1 │ └──261,632 B (00.04%) ── malloc-heap/latin1 ├─────284,952 B (00.04%) ── string(length=25, copies=11873, "Event listenHandler error")/gc-heap/latin1 ├─────284,952 B (00.04%) ── string(length=26, copies=11873, "DOMEventListener.add error")/gc-heap/latin1 ├─────283,560 B (00.04%) ── string(length=25, copies=11815, "DOMEventListener.add load")/gc-heap/latin1 ├──────82,160 B (00.01%) -- string(length=7489, copies=10, "q@https://www.facebook.com/:3:4725/na/o.prototype.componentDidMount@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:623:917/nH@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:65574/nL@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:76662/nK@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:75267/nF@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:73994/nB@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:73217/nz@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:72750/np@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:80028/nu@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:80530/nba/wg.prototype.render@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:96805/nAg/<@https://www.facebook.com/rsrc.php/v3i6FQ4/yn/l/en_US/nge0bBJfXP0.js:142:102965/nV@https://www.facebook.com/rsrc.php/v3i6FQ4" (truncated)) │ ├──81,920 B (00.01%) ── malloc-heap/latin1 │ └─────240 B (00.00%) ── gc-heap/latin1 As you can see above, both short and long strings are duplicated. There is a similar report in bug 1344503. Is there a pattern for creating these strings that Facebook code should avoid? Or can you de-dupe these strings yourselves?
Depends on: 1367471
Just wanted to mention that I looked a little bit more into the about:memory report above and it looks like the duplicate strings are coming from string concatenation in a frequently invoked listener function in our JS code. De-dup during compacting definitely seems like a good idea.
If I ever manage to land nursery strings, another possibility that would work well for something like this is deduplication during tenuring.
De-duplication sounds expensive. Can this not be fixed on the Facebook side?
(In reply to Nicholas Nethercote [:njn] from comment #3) > Can this not be fixed on the Facebook side? Yeah this would be ideal: allocating and then deduplicating this many strings isn't free + it puts more pressure on the GC (heuristics).
~2MB seems not even worth chasing (though admittedly the problem scales). On the JS end this is something we would just close, so -> Tech Evangelism. Maybe it is also not worth doing there. (Apologies if this is the wrong component.)
Component: JavaScript Engine → Desktop
Product: Core → Tech Evangelism
* What is happening in the same scenario in other browsers (Safari, IE, Chrome)? * What are the steps to reproduce? Just "after loading facebook.com while logged in." * Do you know which JavaScript in the page creates this?
Flags: needinfo?(vladan.bugzilla)
Whiteboard: [platform-rel-Facebook] → [platform-rel-Facebook] [needsdiagnosis]
(In reply to Jason Orendorff [:jorendorff] from comment #5) > ~2MB seems not even worth chasing (though admittedly the problem scales). As originally reported on IRC, it was 56MB of ":DIV".
We'll get as much as possible fixed on the Facebook site since it's silly. Let Facebook know if you see anything bad. But it also means for us shipping more JS to avoid redundant copies which isn't great. At least there's still bug 1344503 left to consider mitigating this at the platform level, it would be interesting to know how widespread this issue is across the web.
(In reply to Benoit Girard (:BenWa) from comment #8) > We'll get as much as possible fixed on the Facebook site since it's silly. > Let Facebook know if you see anything bad. But it also means for us shipping > more JS to avoid redundant copies which isn't great. Can you expand on this a little bit? This statement sounds to me like, "we don't want to write more code to make our code more efficient", which seems like a peculiar position.
Flags: needinfo?(b56girard)
Happy to. Facebook already ships a lot of code which the browser has a lot of trouble quickly parsing and booting more. So in our code say we have something like: let handler = 'eventHandler: ' + event.type; We need to replace this with something like: const gStringTable = {}; .... if (!gStringTable[event.type]) { gStringTable[event.type] = 'eventHandler: ' + event.type; } let handler = gStringTable[event.type]; So here we're shipping more code and making startup slower to reduce memory. Generally startup cost is more important to websites like Facebook than memory. Also, unlikely a PGO'ed binary application, where the cost of adding a branch like this is very small and does slow down until you execute nearby code and page this in, with JS this extra line is bloating parse/compile and is slowing down the time to start executing the first statement in the application since the JS engine has to parse every byte in a file. So 3 lines are worth it in this case because where talking about >0.5 MB of memory, the trade off to adding more code to make things more efficient is not a no-brainer.
Flags: needinfo?(b56girard)
If you don't mind a complete, possibly engine-specific, hack: let handler = Object.keys({['eventHandler: ' + event.type]: 0})[0]; will do the same thing using internal data structures. Property names are placed into a lookup table, and you will get the canonical version if you read out a key.
Any updates here Benoit Girard?
Flags: needinfo?(b56girard)
Priority: -- → P1
No updates from me, vladan is looking at memory improvements.
Flags: needinfo?(b56girard)
I landed a fix for this two weeks ago to 50% of users but had to back it out. I'm relanding it today. The 50% is to measure the magnitude of the benefit from fixing this bug (with property atomization suggested in comment 11). FYI the property atomization trick works in both Firefox and Chrome :)
Flags: needinfo?(vladan.bugzilla)
Product: Tech Evangelism → Web Compatibility

See bug 1547409. Moving webcompat whiteboard tags to keywords.

Vladan, can we closet his now?

Flags: needinfo?(vladan.bugzilla)

(In reply to Mike Taylor [:miketaylr] (PTO July 31 - Aug 8) from comment #16)

Vladan, can we closet his now?

Let's do it

Flags: needinfo?(vladan.bugzilla)

according to the previous comment let's close. Thanks everyone.

Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.