Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upEquality for Chars is slow due to `new String(x)` #911
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
process-bot
Sep 29, 2017
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!
Here is what to expect next, and if anyone wants to comment, keep these things in mind.
process-bot
commented
Sep 29, 2017
|
Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it! Here is what to expect next, and if anyone wants to comment, keep these things in mind. |
zwilias
changed the title from
`new String(x)` vs `String(x)`
to
Equality for Chars is slow due to `new String(x)`
Sep 29, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jxxcarlson
Sep 30, 2017
Just a note re the app I am working on. This issue creates a factor-of-700 slowdown running some critical parser/rendering code "for real": 625 milliseconds in elm-test versus 8 seconds in the app
jxxcarlson
commented
Sep 30, 2017
•
|
Just a note re the app I am working on. This issue creates a factor-of-700 slowdown running some critical parser/rendering code "for real": 625 milliseconds in elm-test versus 8 seconds in the app |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
evancz
Sep 30, 2017
Member
It is used by toString to distinguish between "a" and 'a' when showing things.
I would like to make Debug.toString only available in development, which means we could just treat them as strings in production mode.
|
It is used by I would like to make |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
zwilias
Sep 30, 2017
Member
In that case, there is the option of adding yet another case to eqHelp, perhaps only during development:
if (x instanceof String) {
return x.valueOf() === y.valueOf();
}In a quick benchmark, this means 'a' == 'b' would only be ~13% slower than "a" == "b":

(in the screenshot, instanceof means it's the 0.18 core implementation with the above snippet added right after the === check)
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
evancz
Mar 7, 2018
Member
In the development build, the representation is JS strings when in PROD and is the boxed version when in DEBUG to make Debug.toString work right. Probably it can be done without runtime overhead in the future, but that's the thing for now.
|
In the development build, the representation is JS strings when in PROD and is the boxed version when in DEBUG to make |
zwilias commentedSep 29, 2017
•
edited
Edited 1 time
-
zwilias
edited Sep 29, 2017 (most recent)
In the native parts, notable
Utils.chr, theStringobject constructor (new String(x)) is used. This forces the result to be a boxed string, meaning - as far as the JavaScript runtime is concerned - it is anobjectdescribing aString, rather than a primitiveString.This makes equality checks on chars produced by that function extremely slow.
According to this benchmark, equality check for 2 chars is ~100x slower than equality check for 2 strings.
The root cause of that is twofold:
new String('x') !== new String('x'), which means that the short-circuit ineqHelpis skipped.typeof (new String('x')) === 'object'; which meanseqHelpwill take the slow path and check for equality as if it were a record.I can't think of any downsides to using the
Stringprimitive constructor instead (return String(x)). It means equal chars can be checked using===, and callingStringmethods should be equally fast - if not faster - as compared to the StringObject.Following the
git blamehistory, it appears as if chars used to be markedval.isChar = trueat runtime, which may be why it used to be an object, but since the disambiguation happens solely at the type level now,newshould be removed.Maybe
Utils.chrcan actually be removed altogether, I'm not sure what it's purpose is at this point.