The interpreter engine for the core JavaScript language, independent of the browser's object model. File ONLY core JavaScript language bugs in this category. For bugs involving browser objects such as "window" and "document", use the "DOM" component. For bugs involving calls between JavaScript and C++, use the "XPConnect" component.

While profiling ember tests, I noticed that we spend a lot of time in fun_toString, and almost all of the time goes to StringBuffer::append() calls. This is quite sad, but the underlying Vector storage here is quite inefficient. Can we consider using something more efficient, like SegmentedVector perhaps?

(In reply to :Ehsan Akhgari (needinfo please, extremely long backlog) from comment #0)
> […] Can we consider using something more efficient, like
> SegmentedVector perhaps?
SegmentedVector has the issue that it allocates segments of identical sizes, instead of using the increasing size like vectors.
This is an issue because this can be a waste of memory for small content, and this can be an issue as the allocator would appear in the profile for large content. Increasing the allocation size of the segments would reduce the allocator cost for large content, and allow us to make smaller segment first. (maybe inlined, like vectors?)

Fixing fun_toString overhead is on my list for this week. André's suggestion is great.
Offhand, SegmentedVector is not a great fit for StringBuffer because (1) we really want a data structure that supports inline storage as most strings are short and (2) StringBuffer can steal the Vector's underlying buffer and use it for the new string - if we use SegmentedVector we'd need to do another malloc + copy to finish the string.

Good points, thanks! It probably makes sense to first address the issues in fun_toString before considering changes to the underlying data structures, but it still seems to me that we should consider having a more specialized data structure for StringBuffer, perhaps preserving features such as inline buffer stealing and exponential growth of segments but to avoid excessive copying during buffer growth before the string is finished, since I regularly see in profiles where we spend tons of times doing just that. Hopefully a lot of that time is due to issues like what André mentioned which can be more effectively fixed in callers of course. :-)

FWIW on Ember we call fun_toString thousands of times for the closureAction function (642 chars). A 1-slot cache is sufficient to optimize this, but I'll probably go with 2 slots because that does better on Angular (fewer calls but *much* larger functions).
I think a cache for this makes sense: it also hits quite often on random websites, helps avoid allocating duplicate (often large) strings, and worst-case it's just a few pointer comparisons.
Patches for that + comment 1 tomorrow.

Just a simple purged-on-GC cache with 2 entries. It improves the micro-benchmark in the previous comment from 80 ms to 3-4 ms.
I tested this on some real-world websites and it hits quite a lot - when loading cnn.com for instance there are ~10 hits for a 40 KB (IIRC) function.
It might even be worth using a HashMap for this, but for now this will do.