V8's JSON parser is slow |
|||||
Issue descriptionI've attached a microbenchmark that's based on speedometer's VanillaJS usage. You can run them by placing it inside src/third_party/WebKit/PerformanceTests/ Here are some numbers: Chrome canary 63.0.3231.0: Time: values 11.15903295820384, 11.174308030975174, 11.220951761128378, 11.140385568744525, 11.073154797167497, 11.168192986374809, 11.117040199217344, 11.214219630491435, 11.17355889024214, 10.922038489263636, 11.050029006326136, 10.90173719182152, 11.007699886070307, 10.934219734079782, 11.041427435738889, 10.107033484601954, 11.049723756906054, 10.977249650100141, 10.994145617458694, 10.995838075288487 runs/s avg 11.021099357510037 runs/s median 11.049876381616095 runs/s stdev 0.2365787306034051 runs/s min 10.107033484601954 runs/s max 11.220951761128378 runs/s Safari 11.0 (12604.1.38.1.7): Time: values 12.461059190031152, 12.812299807815506, 12.561236025624924, 12.545477355413368, 12.690355329949238, 12.60716086737267, 12.6135216952573, 12.787723785166241, 12.465719272001998, 12.462612163509478, 12.631047113805751, 12.489072061945786, 12.763241863433311, 12.130033964095105, 12.56755058439109, 12.592872434202265, 12.799180852425456, 12.67587780453797, 12.820512820512791, 12.727504136438892 runs/s avg 12.610202956396513 runs/s median 12.610341281314984 runs/s stdev 0.16535712651697212 runs/s min 12.130033964095105 runs/s max 12.820512820512791 runs/s Firefox nightly 58.0a1 (2017-10-03) (64-bit): Time: values 15.03386377816031, 15.17997760953303, 16.308757395002182, 14.688008342788732, 15.52126218904121, 15.120872474341757, 15.768766803592126, 15.927751718206215, 14.667756969934766, 15.176752250902064, 15.731742329792374, 15.709993519627664, 15.188681394624721, 14.99222278443056, 16.065353859500483, 14.91107408194385, 15.614265192680021, 15.032790273784702, 15.330428217186164, 16.29400910020404 runs/s avg 15.41321651426385 runs/s median 15.259554805905442 runs/s stdev 0.4967561754516186 runs/s min 14.667756969934766 runs/s max 16.308757395002182 runs/s Firefox beat us by ~40% on this microbenchmark, and Safari also consistently beat us by a smaller margin, but still significant ~15% margin. We should investigate whether we can improve these numbers.
,
Oct 4 2017
The following revision refers to this bug: https://chromium.googlesource.com/v8/v8.git/+/a7ecf7d4ee542f5c6e1819d94e1aa3ab04081ff1 commit a7ecf7d4ee542f5c6e1819d94e1aa3ab04081ff1 Author: Toon Verwaest <verwaest@chromium.org> Date: Wed Oct 04 15:01:29 2017 Inline relevant parts of MigrateToMap into AllocateStorageForMap This speeds up the json parser by 10-20% Bug: chromium:771227 Change-Id: Ib2392471bdd9ff9041237708cb272229b5ece410 Reviewed-on: https://chromium-review.googlesource.com/700494 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#48287} [modify] https://crrev.com/a7ecf7d4ee542f5c6e1819d94e1aa3ab04081ff1/src/objects.cc
,
Oct 5 2017
Thanks! I just tested today's canary which contains your improvement, here are some numbers: Time: values 11.981141682990975, 11.848341232227492, 11.803031018365512, 11.970456912340339, 11.977697527204342, 11.810558639423647, 11.372165487752175, 11.787170843254188, 12.060616659329785, 11.500730296373817, 11.982649124068363, 11.901503159849096, 11.973323435385979, 12.018075185078333, 11.947574045090121, 12.012372743926239, 11.859512218262465, 11.862959096517022, 12.0500801330329, 12.048120192047021 runs/s avg 11.888403981625988 runs/s median 11.95901547871523 runs/s stdev 0.17771026565578585 runs/s min 11.372165487752175 runs/s max 12.060616659329785 runs/s
,
Oct 5 2017
Also, the perf dashboard for speedometer's VanillaJS shows an improvement for Linux and Mac (Windows didn't change much, and I can confirm on my windows box that there wasn't an improvement -- hopefully this will change with clang on windows). https://chromeperf.appspot.com/report?sid=7e09cfe84f43452952e6a3220140c2b9658d0643de47d2ff2ac3e89d4c3df93b
,
Oct 18 2017
For what it's worth, the change in #2 is also a 20% speedup in the structured deserializer (postMessage etc.), which is similar to the JSON parser. Awesome work!
,
Oct 18 2017
,
Nov 24 2017
I've got a few ideas for relatively-micro stuff that might squeeze another bit out of here.
,
Nov 24 2017
What exactly? I've put optimizing the JSON parser on marja's plate. She'll look into replacing the recursive descent parser with a tight loop using a single zone stack (instead of multiple zonelists).
,
Nov 27 2017
Ah, I wasn't aware Marja was going to look at this. I have a CL to avoid reallocating the properties ZoneVector by using a single ZoneVector stack for the entire time: https://chromium-review.googlesource.com/c/v8/v8/+/789511 (And a similar trick for elements seems useful, even though it doesn't matter for the Speedometer case.) I was also going to look at shuffling around when the JSObject is actually created, since doing the allocation and then later the AllocateStorageForMap seems to be slower than just doing the allocation with the final map (at least for the transitioning fast path). I've done a little poking at that, but haven't polished a CL yet. I'm sure a deeper look at improving the parser loop would yield results; I don't mean to interfere with such work.
,
Nov 28 2017
The following revision refers to this bug: https://chromium.googlesource.com/v8/v8.git/+/d3104923b24180d32747287ba51b41e4af8b0da7 commit d3104923b24180d32747287ba51b41e4af8b0da7 Author: Jeremy Roman <jbroman@chromium.org> Date: Tue Nov 28 22:53:50 2017 Implement and use VectorSegment to avoid repeated allocation of ZoneVector properties. The parser holds a single vector whose backing storage is reused in calls to ParseJsonObject, so that once we reach the peak number of unstored properties no more allocations are required. This improves performance of parsing inputs like those in Speedometer VanillaJS by about 2% in my local measurement, and would presumably do better on more pathological inputs. This should also have the side effect of reducing peak memory usage at this time slightly, since we do fewer zone allocations which cannot be freed until the parse finishes. Bug: chromium:771227 Change-Id: I8aa1514b37a74f82539f95f94292c8fa1582d66a Reviewed-on: https://chromium-review.googlesource.com/789511 Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Jeremy Roman <jbroman@chromium.org> Cr-Commit-Position: refs/heads/master@{#49693} [modify] https://crrev.com/d3104923b24180d32747287ba51b41e4af8b0da7/src/json-parser.cc [modify] https://crrev.com/d3104923b24180d32747287ba51b41e4af8b0da7/src/json-parser.h
,
Nov 29 2017
The following revision refers to this bug: https://chromium.googlesource.com/v8/v8.git/+/32033f4f4fdf96986a32d9fd97da5cacd814795c commit 32033f4f4fdf96986a32d9fd97da5cacd814795c Author: Michael Achenbach <machenbach@chromium.org> Date: Wed Nov 29 10:57:48 2017 Revert "Implement and use VectorSegment to avoid repeated allocation of ZoneVector properties." This reverts commit d3104923b24180d32747287ba51b41e4af8b0da7. Reason for revert: Breaks win debug, causes lots of timeouts. https://build.chromium.org/p/client.v8/builders/V8%20Win64%20-%20debug/builds/20387 Original change's description: > Implement and use VectorSegment to avoid repeated allocation of ZoneVector properties. > > The parser holds a single vector whose backing storage is reused in calls > to ParseJsonObject, so that once we reach the peak number of unstored > properties no more allocations are required. > > This improves performance of parsing inputs like those in Speedometer VanillaJS > by about 2% in my local measurement, and would presumably do better on more > pathological inputs. > > This should also have the side effect of reducing peak memory usage at this time > slightly, since we do fewer zone allocations which cannot be freed until the > parse finishes. > > Bug: chromium:771227 > Change-Id: I8aa1514b37a74f82539f95f94292c8fa1582d66a > Reviewed-on: https://chromium-review.googlesource.com/789511 > Reviewed-by: Camillo Bruni <cbruni@chromium.org> > Reviewed-by: Marja Hölttä <marja@chromium.org> > Commit-Queue: Jeremy Roman <jbroman@chromium.org> > Cr-Commit-Position: refs/heads/master@{#49693} TBR=jbroman@chromium.org,marja@chromium.org,cbruni@chromium.org Change-Id: I5b198aeffed6f1543f6110709dc74b311d4ba144 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: chromium:771227 Reviewed-on: https://chromium-review.googlesource.com/796151 Reviewed-by: Michael Achenbach <machenbach@chromium.org> Commit-Queue: Michael Achenbach <machenbach@chromium.org> Cr-Commit-Position: refs/heads/master@{#49705} [modify] https://crrev.com/32033f4f4fdf96986a32d9fd97da5cacd814795c/src/json-parser.cc [modify] https://crrev.com/32033f4f4fdf96986a32d9fd97da5cacd814795c/src/json-parser.h
,
Dec 11 2017
The following revision refers to this bug: https://chromium.googlesource.com/v8/v8.git/+/d01428579cdf65eba2b0a2ff1d989bbe16f44608 commit d01428579cdf65eba2b0a2ff1d989bbe16f44608 Author: Jeremy Roman <jbroman@chromium.org> Date: Mon Dec 11 15:30:55 2017 Reland: Implement and use VectorSegment to avoid repeated allocation of ZoneVector properties. The parser holds a single vector whose backing storage is reused in calls to ParseJsonObject, so that once we reach the peak number of unstored properties no more allocations are required. This improves performance of parsing inputs like those in Speedometer VanillaJS by about 2% in my local measurement, and would presumably do better on more pathological inputs. This should also have the side effect of reducing peak memory usage at this time slightly, since we do fewer zone allocations which cannot be freed until the parse finishes. Reland switches to use std::vector::data instead of operator[] to avoid an index check in debug MSVC. In such cases the out-of-bounds pointer cannot be dereferenced, so it is legal. Bug: chromium:771227 Change-Id: I21837196372c904bfc799cd14353a73d11dcff32 Reviewed-on: https://chromium-review.googlesource.com/804062 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Jeremy Roman <jbroman@chromium.org> Cr-Commit-Position: refs/heads/master@{#49997} [modify] https://crrev.com/d01428579cdf65eba2b0a2ff1d989bbe16f44608/src/json-parser.cc [modify] https://crrev.com/d01428579cdf65eba2b0a2ff1d989bbe16f44608/src/json-parser.h
,
Feb 2 2018
,
Feb 2 2018
|
|||||
►
Sign in to add a comment |
|||||
Comment 1 by adamk@chromium.org
, Oct 3 2017Status: Available (was: Untriaged)