最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Large substrings ~9000x faster in Firefox than Chrome: why? - Stack Overflow

programmeradmin4浏览0评论

The Benchmark:

So, I'm starting up my very first HTML5 browser-based client-side project. It's going to have to parse very, very large text files into, essentially, an array or arrays of objects. I know how I'm going to go about coding it; my primary concern right now is getting the parser code as fast as I can get it, and my primary testbed is Chrome. However, while looking at the differences between substring methods (I haven't touched JavaScript in a long, long time), I noticed that this benchmark was incredibly slow in Chrome pared to FireFox. Why?

My first assumption is that it has to do with the way FireFox's JS engine would handle string objects, and that for FireFox this operation is simple pointer manipulation, while for Chrome it's actually doing hard copies. But, I'm not sure why Chrome wouldn't do pointer manipulation or why FireFox would. Anyone have some insight?

JSPerf appears to be throwing out my FireFox results, not displaying them on the BrowserScope. For me, I'm getting 9,568,203 ±1.44% Ops/sec on .substr() in FF4.

Edit: So I see a FF3.5 performance result down there actually below Chrome. So I decided to test my pointers hypothesis. This brought me to a 2nd revision of my Substrings test, which is doing 1,092,718±1.62% Ops/sec in FF4 versus 1,195±3.81% Ops/sec in Chrome, down to only 1000x faster, but still an inexplicable difference in performance.

A postscriptum: No, I'm not concerned one lick about Internet Explorer. I'm concerned about trying to improve my skills and getting to know this language on a deeper level.

The Benchmark: http://jsperf./substringing

So, I'm starting up my very first HTML5 browser-based client-side project. It's going to have to parse very, very large text files into, essentially, an array or arrays of objects. I know how I'm going to go about coding it; my primary concern right now is getting the parser code as fast as I can get it, and my primary testbed is Chrome. However, while looking at the differences between substring methods (I haven't touched JavaScript in a long, long time), I noticed that this benchmark was incredibly slow in Chrome pared to FireFox. Why?

My first assumption is that it has to do with the way FireFox's JS engine would handle string objects, and that for FireFox this operation is simple pointer manipulation, while for Chrome it's actually doing hard copies. But, I'm not sure why Chrome wouldn't do pointer manipulation or why FireFox would. Anyone have some insight?

JSPerf appears to be throwing out my FireFox results, not displaying them on the BrowserScope. For me, I'm getting 9,568,203 ±1.44% Ops/sec on .substr() in FF4.

Edit: So I see a FF3.5 performance result down there actually below Chrome. So I decided to test my pointers hypothesis. This brought me to a 2nd revision of my Substrings test, which is doing 1,092,718±1.62% Ops/sec in FF4 versus 1,195±3.81% Ops/sec in Chrome, down to only 1000x faster, but still an inexplicable difference in performance.

A postscriptum: No, I'm not concerned one lick about Internet Explorer. I'm concerned about trying to improve my skills and getting to know this language on a deeper level.

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked May 31, 2011 at 22:53 MischaNixMischaNix 7303 silver badges9 bronze badges 11
  • 4 Link is at the very top, in a header. Or...? – MischaNix Commented May 31, 2011 at 23:03
  • I have no idea how it is implemented, but if you are parsing could you replace substringing with iteration over strings? AFAIK many parsing algorithms are more stream oriented. – Gabriel Ščerbák Commented May 31, 2011 at 23:06
  • I am iterating over the string with an index, but I still have to extract substrings to get my data out of the file. – MischaNix Commented May 31, 2011 at 23:13
  • 1 I'm seeing ~1.1k/s in Chrome 11 and ~250/s in FF3.6. – CanSpice Commented May 31, 2011 at 23:50
  • 1 You could try to parse it as a stream, while not using any substring type functions... If there is a marker at the start of a field, simply append each character into a variable until the end of the filed is reached. This variable would contain the whole field with never having to use a substring method. The appending of a character to the variable should be insanely fast by parison. – Justin808 Commented Jun 1, 2011 at 0:00
 |  Show 6 more ments

2 Answers 2

Reset to default 17

In the case of Spidermonkey (the JS engine in Firefox), a substring() call just creates a new "dependent string": a string object that stores a pointer to the thing it's a substring off and the start and end offsets. This is precisely to make substring() fast, and is an obvious optimization given immutable strings.

As for why V8 does not do that... A possibility is that V8 is trying to save space: in the dependent string setup if you hold on to the substring but forget the original string, the original string can't get GCed because the substring is using part of its string data.

In any case, I just looked at the V8 source, ans it looks like they just don't do any sort of dependent strings at all; the ments don't explain why they don't, though.

[Update, 12/2013]: A few months after I gave the above answer V8 added support for dependent strings, as Paul Draper points out.

Have you eliminated the reading of .length from your benchmark results?

I believe V8 has a few representations of a string:

1. a sequence of ASCII bytes
2. a sequence of UTF-16 code units.
3. a slice of a string (result of substring)
4. a concatenation of two strings.

Number 4 is what makes string += efficient.

I'm just guessing but if they're trying to pack two string pointers and a length into a small space, they may not be able to cache large lengths with the pointers, so may end up walking the joined link list in order to pute the length. This assumes of course that Array.prototype.join creates strings of form (4) from the array parts.

It does lead to a testable hypothesis which would explain the discrepancy even absent buffer copies.

EDIT:

I looked through the V8 source code and StringBuilderConcat is where I would start pulling, especially runtime.

发布评论

评论列表(0)

  1. 暂无评论