New issue
Advanced search Search tips

Issue 920400 link

Starred by 1 user

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

ToNumber(Null) and ToNumber(Undefined) are 1.5x-2x slower than ToNumber(number)

Project Member Reported by esprehn@chromium.org, Jan 9

Issue description

Google Chrome	71.0.3578.98 (Official Build) (64-bit)
Revision	15234034d19b85dcd9a03b164ae89d04145d8368-refs/branch-heads/3578@{#897}
OS	Mac OS X

t = performance.now(); for (let i = 0; i < 100000; i++) clearTimeout(0); performance.now() - t;
10.29999999445863

t = performance.now(); for (let i = 0; i < 100000; i++) clearTimeout(null); performance.now() - t;
21.699999997508712

t = performance.now(); for (let i = 0; i < 100000; i++) clearTimeout(undefined); performance.now() - t;
10.10000001406297

Looking at the code there's a special case that converts undefined to zero, but calling into ToInt32Slow for null is sure enough 2x slower than the fast path for UInt32.

If I'm reading the code right it looks like the conversion happens in Oddball::ToNumber, I'm surprised that's 2x slower, perhaps because there's so much checking overhead before we get to the IsOddball check? Can the blink bindings have a fast path for this like they do for IsUndefined() ?
 
Description: Show this description
Cc: peria@chromium.org
Status: Available (was: Untriaged)

Comment 3 by peria@chromium.org, Jan 18 (4 days ago)

Owner: peria@chromium.org
Status: Assigned (was: Available)
As far as I tested, bindings layer does not have so much checks before calling v8::Value::ToNumber().
Some results are on bottom of this post.

In spec, ES[1] defines conversions of Undefined->Nan and Null->0, and WebIDL[2] defines how to handle exceptional values.
However, in our implementation, we have a fast path only for Undefined in generated code (not in NativeValueTraits<IDLLong>), and null values are handled in Value::ToNumber().

I think it good to
- do not have the fast path for Undefined in the generated code
- have the fast path both for Undefined and Null in NativeValueTraits<IDLLong>
and ask V8 to improve the performance of ToNumber() for Undefined and Null values.


[1] https://tc39.github.io/ecma262/#sec-tonumber
[2] https://heycam.github.io/webidl/#abstract-opdef-converttoint


-----------
Here are my experiments' results. The key point is how we convert a V8 value |v| to an int32 value |x|.

#result for the original code, as a base line.
0        : 15.94499999191612
null     : 25.98000003490597
undefined: 13.819999992847443


#code : Simplify bindings code most.
int x = v->ToNumber();

#result
0        : 15.409999992698431
null     : 21.92500000819564
undefined: 21.87000005505979


#code : Have fast path for Undefined (close to the original one)
int x = (v->IsUndefined()) ? 0 : v->ToNumber();

#result
0        : 15.690000029280782
null     : 22.240000078454614
undefined: 13.155000051483512


#code : Have fast path for Null and Undefined
int x = (v->IsNullOrUndefined()) ? 0 : v->ToNumber();

#result
0        : 12.620000052265823
null     : 10.445000021718442
undefined: 10.175000061281025


Comment 4 by peria@chromium.org, Jan 21 (2 days ago)

Small updates and correction.
Checking if the value is undefined in the bindings layer comes from the default value
  void clearTimeout(optional long handle = 0);
so we can't remove this.

Then what we can do is to insert a fast path for Null in ToInt32Slow().

Comment 5 by peria@chromium.org, Jan 21 (2 days ago)

Components: Blink>JavaScript
Summary: ToNumber(Null) and ToNumber(Undefined) are 1.5x-2x slower than ToNumber(number) (was: clearTimeout(null) is 2x slower than clearTImeout(0) or clearTimeout(undefined))

Sign in to add a comment