New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 772042 link

Starred by 2 users

Issue metadata

Status: WontFix
Owner:
Closed: Oct 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Mac
Pri: 2
Type: Bug



Sign in to add a comment

String.charAt performance regression

Reported by thex...@gmail.com, Oct 5 2017

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

Steps to reproduce the problem:
https://jsperf.com/indexof-vs-charat

In Chrome stable I get these results:
indexOf 954,240,572
charAt 	966,070,635

And in Canary (63 and 62) these results are:
indexOf 956,494,938
charAt  270,937,162 (72% slower)

I do understand that using jsperf.com isn't very scientific, but hopefully the reason for this can be found.

What is the expected behavior?
charAt is faster than indexOf

What went wrong?
charAt is slower than indexOf

Did this work before? N/A 

Chrome version: 63.0.3233.0  Channel: canary
OS Version: 10.0
Flash Version:
 
Components: -Blink Blink>JavaScript

Comment 2 by woxxom@gmail.com, Oct 6 2017

I'm attaching a simplified test.html.
Expected: approximately same times displayed in all tests (100ms)
	charCodeAt   106 ms
	charAt       105 ms
	charAt + if  106 ms
	indexOf      104 ms
Observed: "charAt + if" takes several times longer than other tests (390 - 700ms)
	charCodeAt   106 ms
	charAt       105 ms
	charAt + if  390 ms
	indexOf      104 ms

* Can't bisect chromium snapshots because the issue is not observed there.
* The issue is not observed in incognito window in Chrome Canary
* The issue disappears for one browser session when v8-cache-options flag is cycled:
  disable chrome://flags/#v8-cache-options and restart
  enable chrome://flags/#v8-cache-options and restart
  run test.html
test.html
1.4 KB View Download
Cc: hdodda@chromium.org
Labels: M-63 OS-Linux OS-Mac
Status: Untriaged (was: Unconfirmed)
Able to reproduce the issue on windows 10, mac os 10.12.6 and ubuntu 14.04  using M61 #61.0.3163.100 and M63 #63.0.3236.0 as per comment #2.

As per comment #2 , the issue disappears when we refersh the page and hence unable to bisect the issue.

Marking it as untraiged , so that it would get addressed by respective team .

Thanks!
Cc: bmeu...@chromium.org yangguo@chromium.org
Components: -Blink>JavaScript Blink>JavaScript>Runtime
Labels: Performance
Status: Available (was: Untriaged)
Cc: mathias@chromium.org jarin@chromium.org
Owner: bmeu...@chromium.org
Status: WontFix (was: Available)
This seems to be highly dependent on specific dead code elimination, since the values aren't really used. Here's a simplified test case that runs in d8 and where we also don't use any of the computed values.

=============< bench-string-char-at.js >============================
if (typeof console === 'undefined') console = {log:print};

const N = 1e8;
const TESTS = [];

(function() {
  var string = 'xhdhdfhdfhdfjfjfgjgf';
  TESTS.push(
    function charCodeAt() {
      for (var i = 0; i < N; i++) {
        var result = string.charCodeAt(0);
     }
    },
    function charAt() {
      for (var i = 0; i < N; i++) {
        var result = string.charAt(0);
     }
    },
    function charAtWithIf() {
      for (var i = 0; i < N; i++) {
        if (string.charAt(0) === 'x') {}
     }
    },
    function indexOf() {
      for (var i = 0; i < N; i++) {
        var result = string.indexOf('x');
     }
    },
    function empty() {
      for (var i = 0; i < N; i++) { }
    }
  );
})();

function test(fn) {
  var result;
  result = fn();
  return result;
}

test(x => x);

for (var j = 0; j < TESTS.length; ++j) {
  test(TESTS[j]);
}

for (var j = 0; j < TESTS.length; ++j) {
  var startTime = Date.now();
  test(TESTS[j]);
  console.log(TESTS[j].name + ':', (Date.now() - startTime), 'ms.');
}
====================================================================

Running this with V8 6.1 and ToT I get:

====================================================================
$ ./d8-6.1.534.15 bench-string-char-at.js
charCodeAt: 81 ms.
charAt: 80 ms.
charAtWithIf: 81 ms.
indexOf: 80 ms.
empty: 81 ms.
$ out/Release/d8 bench-string-char-at.js
charCodeAt: 81 ms.
charAt: 80 ms.
charAtWithIf: 80 ms.
indexOf: 81 ms.
empty: 80 ms.
====================================================================

As you can see the optimizing compiler eliminates all the code in the loop and effectively turns it into an empty loop. So this test doesn't really measure indexOf vs. charAt. The fact that you get different results sometimes probably means that the tiering up decisions vary, which happens. For example when the VM decides to optimize while the loop is running (via so-called OSR), it'll not be able to eliminate all the dead code always.

Sign in to add a comment