diff --git a/intl/benchmarks/perftest.ini b/intl/benchmarks/perftest.ini index b1f839b9f3b9..390c0636c8b4 100644 --- a/intl/benchmarks/perftest.ini +++ b/intl/benchmarks/perftest.ini @@ -1,3 +1,4 @@ [perftest_dateTimeFormat.js] [perftest_locale.js] +[perftest_numberFormat.js] [perftest_pluralRules.js] diff --git a/intl/benchmarks/perftest_numberFormat.js b/intl/benchmarks/perftest_numberFormat.js new file mode 100644 index 000000000000..c2a254c6ab41 --- /dev/null +++ b/intl/benchmarks/perftest_numberFormat.js @@ -0,0 +1,221 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +// @ts-check + +var perfMetadata = { + owner: "Internationalization Team", + name: "Intl.NumberFormat", + description: "Test the speed of the Intl.NumberFormat implementation.", + options: { + default: { + perfherder: true, + perfherder_metrics: [ + { + name: "Intl.NumberFormat constructor iterations", + unit: "iterations", + }, + { name: "Intl.NumberFormat constructor accumulatedTime", unit: "ms" }, + { name: "Intl.NumberFormat constructor perCallTime", unit: "ms" }, + + { + name: "Intl.NumberFormat.prototype.format iterations", + unit: "iterations", + }, + { + name: "Intl.NumberFormat.prototype.format accumulatedTime", + unit: "ms", + }, + { + name: "Intl.NumberFormat.prototype.format perCallTime", + unit: "ms", + }, + + { + name: "Intl.NumberFormat.prototype.formatToParts iterations", + unit: "iterations", + }, + { + name: "Intl.NumberFormat.prototype.formatToParts accumulatedTime", + unit: "ms", + }, + { + name: "Intl.NumberFormat.prototype.formatToParts perCallTime", + unit: "ms", + }, + ], + verbose: true, + }, + }, + tags: ["intl", "ecma402"], +}; + +add_task(function measure_numberformat() { + const measureConstructor = measureIterations("Intl.NumberFormat constructor"); + const measureFormat = measureIterations("Intl.NumberFormat.prototype.format"); + const measureFormatToParts = measureIterations( + "Intl.NumberFormat.prototype.formatToParts" + ); + + // Re-use the config between runs. + + const styles = ["decimal", "percent", "currency", "unit"]; + + const numberStyles = [ + "arab", + "arabext", + "bali", + "beng", + "deva", + "fullwide", + "gujr", + "guru", + "hanidec", + "khmr", + "knda", + "laoo", + "latn", + "limb", + "mlym", + "mong", + "mymr", + "orya", + "tamldec", + "telu", + "thai", + "tibt", + ]; + + const decimalOptions = { + notation: ["scientific", "engineering", "compact"], + useGroup: [true, false], + }; + + const currencyOptions = { + currency: ["USD", "CAD", "EUR", "Yen", "MXN", "SAR", "INR", "CNY", "IDR"], + currencyDisplay: ["symbol", "narrowSymbol", "code", "name"], + currencySign: ["accounting", "standard"], + }; + + const unitOptions = { + unit: [ + "acre", + "bit", + "byte", + "celsius", + "centimeter", + "day", + "degree", + "fahrenheit", + "fluid-ounce", + "foot", + "gallon", + "gigabit", + "gigabyte", + "gram", + "hectare", + "hour", + "inch", + "kilobit", + "kilobyte", + "kilogram", + "kilometer", + "liter", + "megabit", + "megabyte", + "meter", + "mile", + "mile-scandinavian", + "milliliter", + "millimeter", + "millisecond", + "minute", + "month", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year", + "meter-per-second", + "kilometer-per-hour", + ], + unitDisplay: ["long", "short", "narrow"], + }; + + function choose(options) { + return options[Math.floor(options.length * prng())]; + } + + function randomizeConfig(config, options) { + for (let option in options) { + config[option] = choose(options[option]); + } + } + + // Split each step of the benchmark into separate JS functions so that performance + // profiles are easy to analyze. + + function benchmarkNumberFormatConstructor() { + for (let i = 0; i < 1000; i++) { + // Create a random configuration powered by a pseudo-random number generator. This + // way the configurations will be the same between 2 different runs. + const locale = pickRepresentativeLocale(); + const style = choose(styles); + const nu = choose(numberStyles); + let config = { + style, + nu, + }; + if (style == "decimal") { + randomizeConfig(config, decimalOptions); + } else if (style == "currency") { + randomizeConfig(config, currencyOptions); + } else if (style == "unit") { + randomizeConfig(config, unitOptions); + } + + // Measure the constructor. + measureConstructor.start(); + const formatter = Intl.NumberFormat(locale, config); + // Also include one format operation to ensure the constructor is de-lazified. + formatter.format(0); + measureConstructor.stop(); + + benchmarkFormatOperation(formatter); + benchmarkFormatToPartsOperation(formatter); + } + } + + function benchmarkFormatOperation(formatter) { + // Measure the format operation. + for (let j = 0; j < 100; j++) { + let num = -1e6 + prng() * 2e6; + measureFormat.start(); + formatter.format(num); + measureFormat.stop(); + } + } + + function benchmarkFormatToPartsOperation(formatter) { + // Measure the formatToParts operation. + for (let j = 0; j < 100; j++) { + let num = -1e6 + prng() * 2e6; + measureFormatToParts.start(); + formatter.formatToParts(num); + measureFormatToParts.stop(); + } + } + + benchmarkNumberFormatConstructor(); + measureConstructor.reportMetrics(); + measureFormat.reportMetrics(); + measureFormatToParts.reportMetrics(); + + ok(true); +}); diff --git a/intl/benchmarks/xpcshell.ini b/intl/benchmarks/xpcshell.ini index 6b6ea62f9025..6e0935be0e3a 100644 --- a/intl/benchmarks/xpcshell.ini +++ b/intl/benchmarks/xpcshell.ini @@ -10,5 +10,8 @@ skip-if = true [perftest_locale.js] skip-if = true +[perftest_numberFormat.js] +skip-if = true + [perftest_pluralRules.js] skip-if = true