Commit 011739b1 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Improve Intl constructor performance

Lazy initialize some data once.

$ python -u tools/run_perf.py --binary-override-path   out/x64.release/d8 --filter "JSTests/Intl"   test/js-perf-test/JSTests.json
INFO      >>> Running suite: JSTests/Intl
INFO      >>> Stdout (#1):
NewIntlCollator-Intl(Score): 2047
NewIntlDateTimeFormat-Intl(Score): 26.5
NewIntlNumberFormat-Intl(Score): 449
NewIntlPluralRules-Intl(Score): 670
NewIntlListFormat-Intl(Score): 1762
NewIntlRelativeTimeFormat-Intl(Score): 918


Compare to performance baseline scores in
https://chromium-review.googlesource.com/c/v8/v8/+/1455717

Bug: chromium:928098
Change-Id: I7f213f50eb261474fb38d9592725a101939020d8
Reviewed-on: https://chromium-review.googlesource.com/c/1455727
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59425}
parent 151a0afb
...@@ -250,6 +250,30 @@ class Intl { ...@@ -250,6 +250,30 @@ class Intl {
const std::vector<std::string>& requested_locales, MatcherOption options, const std::vector<std::string>& requested_locales, MatcherOption options,
const std::set<std::string>& relevant_extension_keys); const std::set<std::string>& relevant_extension_keys);
// A helper template to implement the GetAvailableLocales
// Usage in src/objects/js-XXX.cc
//
// const std::set<std::string>& JSXxx::GetAvailableLocales() {
// static base::LazyInstance<Intl::AvailableLocales<icu::YYY>>::type
// available_locales = LAZY_INSTANCE_INITIALIZER;
// return available_locales.Pointer()->Get();
// }
template <typename T>
class AvailableLocales {
public:
AvailableLocales() {
int32_t num_locales = 0;
const icu::Locale* icu_available_locales =
T::getAvailableLocales(num_locales);
set = Intl::BuildLocaleSet(icu_available_locales, num_locales);
}
virtual ~AvailableLocales() {}
const std::set<std::string>& Get() const { return set; }
private:
std::set<std::string> set;
};
// Utility function to set text to BreakIterator. // Utility function to set text to BreakIterator.
static Managed<icu::UnicodeString> SetTextToBreakIterator( static Managed<icu::UnicodeString> SetTextToBreakIterator(
Isolate* isolate, Handle<String> text, Isolate* isolate, Handle<String> text,
......
...@@ -186,11 +186,10 @@ String JSV8BreakIterator::BreakType(Isolate* isolate, ...@@ -186,11 +186,10 @@ String JSV8BreakIterator::BreakType(Isolate* isolate,
return ReadOnlyRoots(isolate).unknown_string(); return ReadOnlyRoots(isolate).unknown_string();
} }
std::set<std::string> JSV8BreakIterator::GetAvailableLocales() { const std::set<std::string>& JSV8BreakIterator::GetAvailableLocales() {
int32_t num_locales = 0; static base::LazyInstance<Intl::AvailableLocales<icu::BreakIterator>>::type
const icu::Locale* icu_available_locales = available_locales = LAZY_INSTANCE_INITIALIZER;
icu::BreakIterator::getAvailableLocales(num_locales); return available_locales.Pointer()->Get();
return Intl::BuildLocaleSet(icu_available_locales, num_locales);
} }
} // namespace internal } // namespace internal
......
...@@ -35,7 +35,7 @@ class JSV8BreakIterator : public JSObject { ...@@ -35,7 +35,7 @@ class JSV8BreakIterator : public JSObject {
static Handle<JSObject> ResolvedOptions( static Handle<JSObject> ResolvedOptions(
Isolate* isolate, Handle<JSV8BreakIterator> break_iterator); Isolate* isolate, Handle<JSV8BreakIterator> break_iterator);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
static void AdoptText(Isolate* isolate, static void AdoptText(Isolate* isolate,
Handle<JSV8BreakIterator> break_iterator, Handle<JSV8BreakIterator> break_iterator,
......
...@@ -484,11 +484,10 @@ MaybeHandle<JSCollator> JSCollator::Initialize(Isolate* isolate, ...@@ -484,11 +484,10 @@ MaybeHandle<JSCollator> JSCollator::Initialize(Isolate* isolate,
return collator; return collator;
} }
std::set<std::string> JSCollator::GetAvailableLocales() { const std::set<std::string>& JSCollator::GetAvailableLocales() {
int32_t num_locales = 0; static base::LazyInstance<Intl::AvailableLocales<icu::Collator>>::type
const icu::Locale* icu_available_locales = available_locales = LAZY_INSTANCE_INITIALIZER;
icu::Collator::getAvailableLocales(num_locales); return available_locales.Pointer()->Get();
return Intl::BuildLocaleSet(icu_available_locales, num_locales);
} }
} // namespace internal } // namespace internal
......
...@@ -40,7 +40,7 @@ class JSCollator : public JSObject { ...@@ -40,7 +40,7 @@ class JSCollator : public JSObject {
static Handle<JSObject> ResolvedOptions(Isolate* isolate, static Handle<JSObject> ResolvedOptions(Isolate* isolate,
Handle<JSCollator> collator); Handle<JSCollator> collator);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
DECL_CAST(JSCollator) DECL_CAST(JSCollator)
DECL_PRINTER(JSCollator) DECL_PRINTER(JSCollator)
......
...@@ -54,7 +54,7 @@ class PatternItem { ...@@ -54,7 +54,7 @@ class PatternItem {
std::vector<const char*> allowed_values; std::vector<const char*> allowed_values;
}; };
const std::vector<PatternItem> GetPatternItems() { static const std::vector<PatternItem> BuildPatternItems() {
const std::vector<const char*> kLongShort = {"long", "short"}; const std::vector<const char*> kLongShort = {"long", "short"};
const std::vector<const char*> kNarrowLongShort = {"narrow", "long", "short"}; const std::vector<const char*> kNarrowLongShort = {"narrow", "long", "short"};
const std::vector<const char*> k2DigitNumeric = {"2-digit", "numeric"}; const std::vector<const char*> k2DigitNumeric = {"2-digit", "numeric"};
...@@ -107,6 +107,22 @@ const std::vector<PatternItem> GetPatternItems() { ...@@ -107,6 +107,22 @@ const std::vector<PatternItem> GetPatternItems() {
return kPatternItems; return kPatternItems;
} }
class PatternItems {
public:
PatternItems() : data(BuildPatternItems()) {}
virtual ~PatternItems() {}
const std::vector<PatternItem>& Get() const { return data; }
private:
const std::vector<PatternItem> data;
};
static const std::vector<PatternItem>& GetPatternItems() {
static base::LazyInstance<PatternItems>::type items =
LAZY_INSTANCE_INITIALIZER;
return items.Pointer()->Get();
}
class PatternData { class PatternData {
public: public:
PatternData(const std::string property, std::vector<PatternMap> pairs, PatternData(const std::string property, std::vector<PatternMap> pairs,
...@@ -154,23 +170,57 @@ const std::vector<PatternData> CreateData(const char* digit2, ...@@ -154,23 +170,57 @@ const std::vector<PatternData> CreateData(const char* digit2,
// kk 24 // kk 24
// K hour in am/pm (0~11) K 0 // K hour in am/pm (0~11) K 0
// KK 00 // KK 00
const std::vector<PatternData> GetPatternData(Intl::HourCycle hour_cycle) {
const std::vector<PatternData> data = CreateData("jj", "j"); class Pattern {
const std::vector<PatternData> data_h11 = CreateData("KK", "K"); public:
const std::vector<PatternData> data_h12 = CreateData("hh", "h"); Pattern(const char* d1, const char* d2) : data(CreateData(d1, d2)) {}
const std::vector<PatternData> data_h23 = CreateData("HH", "H"); virtual ~Pattern() {}
const std::vector<PatternData> data_h24 = CreateData("kk", "k"); virtual const std::vector<PatternData>& Get() const { return data; }
private:
std::vector<PatternData> data;
};
#define DEFFINE_TRAIT(name, d1, d2) \
struct name { \
static void Construct(void* allocated_ptr) { \
new (allocated_ptr) Pattern(d1, d2); \
} \
};
DEFFINE_TRAIT(H11Trait, "KK", "K")
DEFFINE_TRAIT(H12Trait, "hh", "h")
DEFFINE_TRAIT(H23Trait, "HH", "H")
DEFFINE_TRAIT(H24Trait, "kk", "k")
DEFFINE_TRAIT(HDefaultTrait, "jj", "j")
#undef DEFFINE_TRAIT
const std::vector<PatternData>& GetPatternData(Intl::HourCycle hour_cycle) {
switch (hour_cycle) { switch (hour_cycle) {
case Intl::HourCycle::kH11: case Intl::HourCycle::kH11: {
return data_h11; static base::LazyInstance<Pattern, H11Trait>::type h11 =
case Intl::HourCycle::kH12: LAZY_INSTANCE_INITIALIZER;
return data_h12; return h11.Pointer()->Get();
case Intl::HourCycle::kH23: }
return data_h23; case Intl::HourCycle::kH12: {
case Intl::HourCycle::kH24: static base::LazyInstance<Pattern, H12Trait>::type h12 =
return data_h24; LAZY_INSTANCE_INITIALIZER;
case Intl::HourCycle::kUndefined: return h12.Pointer()->Get();
return data; }
case Intl::HourCycle::kH23: {
static base::LazyInstance<Pattern, H23Trait>::type h23 =
LAZY_INSTANCE_INITIALIZER;
return h23.Pointer()->Get();
}
case Intl::HourCycle::kH24: {
static base::LazyInstance<Pattern, H24Trait>::type h24 =
LAZY_INSTANCE_INITIALIZER;
return h24.Pointer()->Get();
}
case Intl::HourCycle::kUndefined: {
static base::LazyInstance<Pattern, HDefaultTrait>::type hDefault =
LAZY_INSTANCE_INITIALIZER;
return hDefault.Pointer()->Get();
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -1362,11 +1412,10 @@ MaybeHandle<Object> JSDateTimeFormat::FormatToParts( ...@@ -1362,11 +1412,10 @@ MaybeHandle<Object> JSDateTimeFormat::FormatToParts(
return result; return result;
} }
std::set<std::string> JSDateTimeFormat::GetAvailableLocales() { const std::set<std::string>& JSDateTimeFormat::GetAvailableLocales() {
int32_t num_locales = 0; static base::LazyInstance<Intl::AvailableLocales<icu::DateFormat>>::type
const icu::Locale* icu_available_locales = available_locales = LAZY_INSTANCE_INITIALIZER;
icu::DateFormat::getAvailableLocales(num_locales); return available_locales.Pointer()->Get();
return Intl::BuildLocaleSet(icu_available_locales, num_locales);
} }
Handle<String> JSDateTimeFormat::HourCycleAsString() const { Handle<String> JSDateTimeFormat::HourCycleAsString() const {
......
...@@ -71,7 +71,7 @@ class JSDateTimeFormat : public JSObject { ...@@ -71,7 +71,7 @@ class JSDateTimeFormat : public JSObject {
Isolate* isolate, Handle<Object> date, Handle<Object> locales, Isolate* isolate, Handle<Object> date, Handle<Object> locales,
Handle<Object> options, RequiredOption required, DefaultsOption defaults); Handle<Object> options, RequiredOption required, DefaultsOption defaults);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
Handle<String> HourCycleAsString() const; Handle<String> HourCycleAsString() const;
DECL_CAST(JSDateTimeFormat) DECL_CAST(JSDateTimeFormat)
......
...@@ -411,15 +411,14 @@ MaybeHandle<String> JSListFormat::FormatList(Isolate* isolate, ...@@ -411,15 +411,14 @@ MaybeHandle<String> JSListFormat::FormatList(Isolate* isolate,
return Intl::ToString(isolate, formatted); return Intl::ToString(isolate, formatted);
} }
std::set<std::string> JSListFormat::GetAvailableLocales() { const std::set<std::string>& JSListFormat::GetAvailableLocales() {
int32_t num_locales = 0;
// TODO(ftang): for now just use // TODO(ftang): for now just use
// icu::Locale::getAvailableLocales(count) until we migrate to // icu::Locale::getAvailableLocales(count) until we migrate to
// Intl::GetAvailableLocales(). // Intl::GetAvailableLocales().
// ICU FR at https://unicode-org.atlassian.net/browse/ICU-20015 // ICU FR at https://unicode-org.atlassian.net/browse/ICU-20015
const icu::Locale* icu_available_locales = static base::LazyInstance<Intl::AvailableLocales<icu::Locale>>::type
icu::Locale::getAvailableLocales(num_locales); available_locales = LAZY_INSTANCE_INITIALIZER;
return Intl::BuildLocaleSet(icu_available_locales, num_locales); return available_locales.Pointer()->Get();
} }
// ecma42 #sec-formatlisttoparts // ecma42 #sec-formatlisttoparts
......
...@@ -49,7 +49,7 @@ class JSListFormat : public JSObject { ...@@ -49,7 +49,7 @@ class JSListFormat : public JSObject {
Isolate* isolate, Handle<JSListFormat> format_holder, Isolate* isolate, Handle<JSListFormat> format_holder,
Handle<JSArray> list); Handle<JSArray> list);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
Handle<String> StyleAsString() const; Handle<String> StyleAsString() const;
Handle<String> TypeAsString() const; Handle<String> TypeAsString() const;
......
...@@ -747,11 +747,10 @@ MaybeHandle<JSArray> JSNumberFormat::FormatToParts( ...@@ -747,11 +747,10 @@ MaybeHandle<JSArray> JSNumberFormat::FormatToParts(
return result; return result;
} }
std::set<std::string> JSNumberFormat::GetAvailableLocales() { const std::set<std::string>& JSNumberFormat::GetAvailableLocales() {
int32_t num_locales = 0; static base::LazyInstance<Intl::AvailableLocales<icu::NumberFormat>>::type
const icu::Locale* icu_available_locales = available_locales = LAZY_INSTANCE_INITIALIZER;
icu::NumberFormat::getAvailableLocales(num_locales); return available_locales.Pointer()->Get();
return Intl::BuildLocaleSet(icu_available_locales, num_locales);
} }
} // namespace internal } // namespace internal
......
...@@ -64,7 +64,7 @@ class JSNumberFormat : public JSObject { ...@@ -64,7 +64,7 @@ class JSNumberFormat : public JSObject {
Isolate* isolate, const icu::NumberFormat& number_format, Isolate* isolate, const icu::NumberFormat& number_format,
Handle<Object> numeric_obj); Handle<Object> numeric_obj);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
Handle<String> StyleAsString() const; Handle<String> StyleAsString() const;
Handle<String> CurrencyDisplayAsString() const; Handle<String> CurrencyDisplayAsString() const;
......
...@@ -314,16 +314,15 @@ Handle<JSObject> JSPluralRules::ResolvedOptions( ...@@ -314,16 +314,15 @@ Handle<JSObject> JSPluralRules::ResolvedOptions(
return options; return options;
} }
std::set<std::string> JSPluralRules::GetAvailableLocales() { const std::set<std::string>& JSPluralRules::GetAvailableLocales() {
int32_t num_locales = 0;
// TODO(ftang): For PluralRules, filter out locales that // TODO(ftang): For PluralRules, filter out locales that
// don't support PluralRules. // don't support PluralRules.
// PluralRules is missing an appropriate getAvailableLocales method, // PluralRules is missing an appropriate getAvailableLocales method,
// so we should filter from all locales, but it's not clear how; see // so we should filter from all locales, but it's not clear how; see
// https://ssl.icu-project.org/trac/ticket/12756 // https://ssl.icu-project.org/trac/ticket/12756
const icu::Locale* icu_available_locales = static base::LazyInstance<Intl::AvailableLocales<icu::Locale>>::type
icu::Locale::getAvailableLocales(num_locales); available_locales = LAZY_INSTANCE_INITIALIZER;
return Intl::BuildLocaleSet(icu_available_locales, num_locales); return available_locales.Pointer()->Get();
} }
} // namespace internal } // namespace internal
......
...@@ -40,7 +40,7 @@ class JSPluralRules : public JSObject { ...@@ -40,7 +40,7 @@ class JSPluralRules : public JSObject {
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ResolvePlural( V8_WARN_UNUSED_RESULT static MaybeHandle<String> ResolvePlural(
Isolate* isolate, Handle<JSPluralRules> plural_rules, double number); Isolate* isolate, Handle<JSPluralRules> plural_rules, double number);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
// [[Type]] is one of the values "cardinal" or "ordinal", // [[Type]] is one of the values "cardinal" or "ordinal",
// identifying the plural rules used. // identifying the plural rules used.
......
...@@ -409,11 +409,10 @@ MaybeHandle<Object> JSRelativeTimeFormat::Format( ...@@ -409,11 +409,10 @@ MaybeHandle<Object> JSRelativeTimeFormat::Format(
formatted.length())); formatted.length()));
} }
std::set<std::string> JSRelativeTimeFormat::GetAvailableLocales() { const std::set<std::string>& JSRelativeTimeFormat::GetAvailableLocales() {
int32_t num_locales = 0; static base::LazyInstance<Intl::AvailableLocales<icu::DateFormat>>::type
const icu::Locale* icu_available_locales = available_locales = LAZY_INSTANCE_INITIALIZER;
icu::DateFormat::getAvailableLocales(num_locales); return available_locales.Pointer()->Get();
return Intl::BuildLocaleSet(icu_available_locales, num_locales);
} }
} // namespace internal } // namespace internal
......
...@@ -50,7 +50,7 @@ class JSRelativeTimeFormat : public JSObject { ...@@ -50,7 +50,7 @@ class JSRelativeTimeFormat : public JSObject {
Handle<JSRelativeTimeFormat> format_holder, const char* func_name, Handle<JSRelativeTimeFormat> format_holder, const char* func_name,
bool to_parts); bool to_parts);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
DECL_CAST(JSRelativeTimeFormat) DECL_CAST(JSRelativeTimeFormat)
......
...@@ -162,11 +162,10 @@ Handle<String> JSSegmenter::GranularityAsString() const { ...@@ -162,11 +162,10 @@ Handle<String> JSSegmenter::GranularityAsString() const {
} }
} }
std::set<std::string> JSSegmenter::GetAvailableLocales() { const std::set<std::string>& JSSegmenter::GetAvailableLocales() {
int32_t num_locales = 0; static base::LazyInstance<Intl::AvailableLocales<icu::BreakIterator>>::type
const icu::Locale* icu_available_locales = available_locales = LAZY_INSTANCE_INITIALIZER;
icu::BreakIterator::getAvailableLocales(num_locales); return available_locales.Pointer()->Get();
return Intl::BuildLocaleSet(icu_available_locales, num_locales);
} }
} // namespace internal } // namespace internal
......
...@@ -39,7 +39,7 @@ class JSSegmenter : public JSObject { ...@@ -39,7 +39,7 @@ class JSSegmenter : public JSObject {
V8_WARN_UNUSED_RESULT static Handle<JSObject> ResolvedOptions( V8_WARN_UNUSED_RESULT static Handle<JSObject> ResolvedOptions(
Isolate* isolate, Handle<JSSegmenter> segmenter_holder); Isolate* isolate, Handle<JSSegmenter> segmenter_holder);
static std::set<std::string> GetAvailableLocales(); static const std::set<std::string>& GetAvailableLocales();
Handle<String> GranularityAsString() const; Handle<String> GranularityAsString() const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment