Bug 213158 - [JSC] String.protoytpe.toLocaleLowerCase's availableLocales HashSet is inefficient
Summary: [JSC] String.protoytpe.toLocaleLowerCase's availableLocales HashSet is ineffi...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Yusuke Suzuki
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-06-12 17:25 PDT by Yusuke Suzuki
Modified: 2020-07-13 08:28 PDT (History)
12 users (show)

See Also:


Attachments
Patch (3.17 KB, patch)
2020-07-12 17:14 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff
Patch (8.19 KB, patch)
2020-07-12 17:54 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff
Patch (8.22 KB, patch)
2020-07-12 17:57 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff
Patch (8.25 KB, patch)
2020-07-12 18:03 PDT, Yusuke Suzuki
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yusuke Suzuki 2020-06-12 17:25:51 PDT
There are only 4 elements and all of them are two characters strings. We should just have `std::array<ASCIILiteral>` and iterate it, it is much efficient than this.
Comment 1 Yusuke Suzuki 2020-07-12 17:12:47 PDT
Currently, bestAvailableLocale requires HashSet and it is used in the other code.
Maybe, just creating static HashSet would be nice.
Comment 2 Yusuke Suzuki 2020-07-12 17:14:35 PDT
Created attachment 404121 [details]
Patch
Comment 3 Darin Adler 2020-07-12 17:23:08 PDT
Comment on attachment 404121 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=404121&action=review

> Source/JavaScriptCore/runtime/StringPrototype.cpp:1548
> +    static std::once_flag onceKey;
> +    std::call_once(onceKey, [&] {

Since String doesn’t have a thread-safe reference count, using a thread-safe run-once algorithm here isn’t enough to make access to this global shared object thread-safe, so I think this should not be using call_once.

Unless StaticStringImpl is enough to make access to a string thread-safe, in which case, OK!

> Source/JavaScriptCore/runtime/StringPrototype.cpp:1557
> +        static StringImpl::StaticStringImpl az("az");
> +        static StringImpl::StaticStringImpl el("el");
> +        static StringImpl::StaticStringImpl lt("lt");
> +        static StringImpl::StaticStringImpl tr("tr");
> +        availableLocales.construct();
> +        availableLocales->add(&static_cast<StringImpl&>(az));
> +        availableLocales->add(&static_cast<StringImpl&>(el));
> +        availableLocales->add(&static_cast<StringImpl&>(lt));
> +        availableLocales->add(&static_cast<StringImpl&>(tr));

I really wish we had a better idiom for this. The old code was inefficient, but readable. It would be nice if the efficient version was also readable. Even if we had to put some helper functions somewhere.

It seems to me that this might not be the only constant HashSet of strings we ever want to create.

Also, can the StringImpl::StaticStringImpl be const?

Finally, does this need to be a HashSet. For a list of 4 strings I think another kind of set could be efficient, like a constant array that we use binary_search with. Maybe even something that first checks that the string is 2 characters long and then converts the string to a uint16_t and compares against 4 constant values.
Comment 4 Yusuke Suzuki 2020-07-12 17:34:45 PDT
Comment on attachment 404121 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=404121&action=review

I'll try refactoring bestAvailableLocale.

>> Source/JavaScriptCore/runtime/StringPrototype.cpp:1548
>> +    std::call_once(onceKey, [&] {
> 
> Since String doesn’t have a thread-safe reference count, using a thread-safe run-once algorithm here isn’t enough to make access to this global shared object thread-safe, so I think this should not be using call_once.
> 
> Unless StaticStringImpl is enough to make access to a string thread-safe, in which case, OK!

Yes, that's why I used StaticStringImpl! This generates static StringImpl, which can be usable in a thread-safe manner (special ref-count is used and it will be never destroyed).
Comment 5 Yusuke Suzuki 2020-07-12 17:54:03 PDT
Created attachment 404122 [details]
Patch
Comment 6 Yusuke Suzuki 2020-07-12 17:57:44 PDT
Created attachment 404123 [details]
Patch
Comment 7 Yusuke Suzuki 2020-07-12 18:03:29 PDT
Created attachment 404124 [details]
Patch
Comment 8 Darin Adler 2020-07-12 18:33:31 PDT
Comment on attachment 404124 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=404124&action=review

> Source/JavaScriptCore/runtime/IntlObjectInlines.h:40
> +    String candidate = locale;

This would be more efficient if it used StringView; no memory allocation when substring is called.
Comment 9 Yusuke Suzuki 2020-07-12 23:04:42 PDT
Comment on attachment 404124 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=404124&action=review

>> Source/JavaScriptCore/runtime/IntlObjectInlines.h:40
>> +    String candidate = locale;
> 
> This would be more efficient if it used StringView; no memory allocation when substring is called.

Yeah, we should optimize these things in different patches I think. We have a lot of opportunities.
Comment 10 EWS 2020-07-12 23:27:24 PDT
Committed r264293: <https://trac.webkit.org/changeset/264293>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 404124 [details].
Comment 11 Radar WebKit Bug Importer 2020-07-12 23:28:14 PDT
<rdar://problem/65457670>
Comment 12 Darin Adler 2020-07-13 08:28:01 PDT
Comment on attachment 404124 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=404124&action=review

>>> Source/JavaScriptCore/runtime/IntlObjectInlines.h:40
>>> +    String candidate = locale;
>> 
>> This would be more efficient if it used StringView; no memory allocation when substring is called.
> 
> Yeah, we should optimize these things in different patches I think. We have a lot of opportunities.

I commented because the code was *new*.