New issue
Advanced search Search tips

Issue 651637 link

Starred by 6 users

Issue metadata

Status: Fixed
Owner:
Closed: Aug 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Feature

Blocking:
issue v8:5267
issue v8:5460



Sign in to add a comment

Let and const big performance impact

Reported by stephane...@gmail.com, Sep 29 2016

Issue description

UserAgent: 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.
 
Components: -Blink Blink>JavaScript
Labels: Needs-Bisect
Labels: -Needs-Bisect M-55 OS-Linux OS-Mac
Status: Untriaged (was: Unconfirmed)
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
Linux.jpg
32.2 KB View Download
Mac.png
38.1 KB View Download
Windows.PNG
59.0 KB View Download
Cc: littledan@chromium.org adamk@chromium.org
Components: -Blink>JavaScript Blink>JavaScript>Language
Status: Available (was: Untriaged)
I think this is due to ES2015/ES6 related changes which made it simply more costly.

Comment 5 by adamk@chromium.org, Oct 4 2016

Cc: -littledan@chromium.org bmeu...@chromium.org
Components: -Blink>JavaScript>Language Blink>JavaScript>Compiler
Labels: Performance
Relevant to our plans around speeding up let/const. Not sure yet if this is due to TurboFan, hole checks, or something else.
Blocking: v8:5460
Blocking: v8:5267
Cc: jarin@chromium.org
Labels: -OS-Linux -OS-Windows -Type-Bug -OS-Mac OS-All Type-Feature
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.
Labels: -Performance Performance-Loading Needs-Investigation
Cc: -adamk@chromium.org caitp@chromium.org rmcilroy@chromium.org leszeks@chromium.org
Components: -Blink>JavaScript>Compiler Blink>JavaScript>Interpreter
Owner: adamk@chromium.org
Status: Assigned (was: Available)
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?
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?
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...
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.
Status: Started (was: Assigned)
Work in progress: https://chromium-review.googlesource.com/c/494006/
Project Member

Comment 14 by bugdroid1@chromium.org, 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

Status: Fixed (was: Started)

Sign in to add a comment