Let and const big performance impact
Reported by
stephane...@gmail.com,
Sep 29 2016
|
|||||||||||
Issue descriptionUserAgent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 Steps to reproduce the problem: 1. open http://stephaneginier.com/archive/testperf/indexLet.html and http://stephaneginier.com/archive/testperf/indexVar.html 2. click Topology->Remesh 3. Open console to see the timings What is the expected behavior? The timings should be around the same range. (Note that everything is slower, not just the "Topology->Remesh" option) What went wrong? indexLet.html is 4 times slower. The only difference is the usage of const/let instead of var. Did this work before? N/A Chrome version: 53.0.2785.143 Channel: stable OS Version: 10.0 Flash Version: Shockwave Flash 23.0 r0 I don't know how much care let/const have received in term of optimization, but since the feature has been introduced a while ago, I figured it was ok (perf wise) to use let/const. Same result on canary build (55). Firefox doesn't have the issue as both version runs around the same speed.
,
Sep 30 2016
,
Oct 3 2016
Able to reproduce the issue on Windows-10, Ubuntu 14.04 and Mac OS 10.12 using chrome latest stable M53-53.0.2785.143 by following steps mentioned in the original comment. Tested the same on previous version of chrome M35-35.0.1849.0 but unable to view the page. So increased the range till M50-50.0.26240 and observed different timings under console. So considering this to be a non-regression one and marking it as untriaged For reference attaching screen shot of the stable behavior for all 3 OS
,
Oct 4 2016
I think this is due to ES2015/ES6 related changes which made it simply more costly.
,
Oct 4 2016
Relevant to our plans around speeding up let/const. Not sure yet if this is due to TurboFan, hole checks, or something else.
,
Oct 5 2016
,
Oct 5 2016
Without having looked at the code in detail it seems that this is mostly due to TurboFan code not being on par with Crankshaft code yet for some cases. I think let/const itself also plays a role here, but I don't think that's the main bummer here.
,
May 1 2017
,
May 2 2017
Ran it again today with latest Canary:
-------------------------------------
indexVar.html:
1. initMeshes: 73.953857421875ms
2. voxelization: 601.864990234375ms
3. flood: 114.390869140625ms
4. surfaceNet: 425.9091796875ms
remesh total: 1360.0419921875ms
-------------------------------------
-------------------------------------
indexLet.html:
1. initMeshes: 84.283203125ms
2. voxelization: 690.005859375ms
3. flood: 115.863037109375ms
4. surfaceNet: 414.850830078125ms
remesh total: 1449.701171875ms
-------------------------------------
This is almost on par now, it seems that the remaining difference is due to for(let...) scoping that's still not 100% optimized. And it seems that the initialization of let/const locals in Ignition is already more expensive, since we often (always?) store the hole explicitly to initialize the local. I.e.
-------------------------------------
function foo() {
let x = 1;
return x;
}
-------------------------------------
Here we first store the hole into x, just to immediately replace it with 1. It feels like the BytecodeGenerator could be more clever here. Ross, Leszek, Adam, any ideas?
,
May 2 2017
Adam, I thought the parser was trying to be smarter about eliding hole checks when they don't look necessary, is there any reason it misses simple cases like Benedikt's example above? I'm not sure exactly how the bytecode generator could avoid hole checks without either more information from the parser, or having to descend down the assignmet expression and check whether there could side-effects before emitting the code to assign x with undefined and then re-visiting the assigment expression to emit the bytecode for it - I'd rather avoid doing that if possible. Any hints we could add in the parser or alternatively do in another ast visit pass before it gets to the bytecode generator?
,
May 2 2017
Afaik, the parser is smart about eliding hole *checks* on let variable access, but not about setting binding_needs_init on the Variable itself (which is, as near as I can tell, set only on variable creation, before we know anything about side-effects). I reckon the parser could add a "no side-effect RHS" check somewhere in PatternRewriter -- alternatively, I guess I could imagine a change to the bytecode generator which stores current state of registers in an array (for simple loads and stores) rather than outputting them immediately, and dumps them when a side effect is encountered. I'm not sure how expensive the latter would be though...
,
May 2 2017
I don't think PatternRewriter is the place for this, but rather scope analysis. When we're recording accesses to a lexical variable, we could keep track, on the variable, whether any of the accesses needs a hole check. If no such access exists, then we should be able to get away with not storing a hole. I'll experiment with this approach.
,
May 2 2017
Work in progress: https://chromium-review.googlesource.com/c/494006/
,
May 8 2017
The following revision refers to this bug: https://chromium.googlesource.com/v8/v8.git/+/ededfcd21295904a0e9482f7a8546f09e24fdc6d commit ededfcd21295904a0e9482f7a8546f09e24fdc6d Author: Adam Klein <adamk@chromium.org> Date: Mon May 08 19:28:30 2017 Skip hole initialization of lexical variables when possible This patch expands scope analysis to skip hole initialization when it can be determined statically that no hole checks will be generated at runtime. Two conditions must be met to safely eliminate hole initialization: - There must not exist a VariableProxy referencing this Variable whose HoleCheckMode is kRequired - The Variable must be stack allocated; any other allocation implies that it may be accessed from not-yet-analyzed scopes (other modules, inner functions, or eval code) and that code may require hole checks. The new logic required removing debug code in full-codegen which is now incorrect in some cases. Also fixed Variable's bitfield helpers to take no more space than needed. Bug: chromium:651637 Change-Id: Ie5ac326af4e05b7a5c3c37cd4d0afba6a51a504d Reviewed-on: https://chromium-review.googlesource.com/494006 Commit-Queue: Adam Klein <adamk@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#45170} [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/ast/ast.h [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/ast/scopes.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/ast/variables.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/ast/variables.h [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/bailout-reason.h [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/arm/full-codegen-arm.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/arm64/full-codegen-arm64.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/ia32/full-codegen-ia32.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/mips/full-codegen-mips.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/mips64/full-codegen-mips64.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/ppc/full-codegen-ppc.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/s390/full-codegen-s390.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/x64/full-codegen-x64.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/full-codegen/x87/full-codegen-x87.cc [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/src/globals.h [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/ConstVariable.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/LetVariable.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/NewAndSpread.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/interpreter/bytecode_expectations/SuperCallAndSpread.golden [modify] https://crrev.com/ededfcd21295904a0e9482f7a8546f09e24fdc6d/test/cctest/test-serialize.cc
,
Aug 3 2017
|
|||||||||||
►
Sign in to add a comment |
|||||||||||
Comment 1 by schenney@chromium.org
, Sep 30 2016