Skip to content

Instantly share code, notes, and snippets.

@zbraniecki
Last active February 26, 2020 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zbraniecki/c047476fc7435dbd0d62b04e341d56c5 to your computer and use it in GitHub Desktop.
Save zbraniecki/c047476fc7435dbd0d62b04e341d56c5 to your computer and use it in GitHub Desktop.
fluent-rs performance test against about:preferences in Firefox
Since we are caching resources after first run, to test performance, we need to restart the browser between each try.
Steps:
Parsing, old impl:
1) Apply the patchset from https://bugzilla.mozilla.org/show_bug.cgi?id=1560038 until `fluent-bindgen-rs`. Do not apply `fluent-swap-impls` or you'll lose ability to test JS impl.
2) Copy to memory the test.js
3) Start browser
4) Open browser console (ctrl+shift+j)
5) Paste the snippet and launch it
6) Restart browser
7) Repeat steps 4-6 as many times as you want
Resolving, old impl:
1) Apply the patchset from https://bugzilla.mozilla.org/show_bug.cgi?id=1560038 until `fluent-bindgen-rs`. Do not apply `fluent-swap-impls` or you'll lose ability to test JS impl.
2) Copy to memory the test.js, with `includeResolving` set to `true`.
3) Start browser
4) Go to `about:preferences`
5) Open web console (ctrl+shift+i)
6) Paste the snippet and launch it
7) Restart browser
8) Repeat steps 4-7 as many times as you want
This time, collect only `resolve` times (parse times will be affected by the fact that you opened Preferences window and L10nRegistry cached FluentResources).
Testing new impl requires the same steps but with `idlBacked` set to `true`.
{
async function testResolving() {
let l10nElements = Array.from(document.querySelectorAll("[data-l10n-id]")).map(elem => document.l10n.getAttributes(elem));
performance.mark("fluent-resolve-start");
let resolveStart = performance.now();
let values = await document.l10n.formatMessages(l10nElements);
let resolveEnd = performance.now();
performance.mark("fluent-resolve-end");
console.log(`perf(resolve): ${resolveEnd-resolveStart}`);
}
testResolving();
}
{
// CONFIG
const idlBacked = false;
const includeResolving = false;
// CONFIG END
let prefix = "resource://app/localization/en-US/";
let sources = [
{
"prefix": "resource://app/localization/en-US/",
"paths": [
"branding/brand.ftl",
"browser/branding/brandings.ftl",
"browser/branding/sync-brand.ftl",
"browser/preferences/preferences.ftl",
"browser/preferences/fonts.ftl",
"browser/preferences/blocklists.ftl",
"browser/preferences/clearSiteData.ftl",
"browser/preferences/colors.ftl",
"browser/preferences/connection.ftl",
"browser/preferences/languages.ftl",
"browser/preferences/permissions.ftl",
"browser/preferences/selectBookmark.ftl",
"browser/preferences/siteDataSettings.ftl",
"browser/aboutDialog.ftl",
"browser/sanitize.ftl",
]
},
{
"prefix": "resource://gre/localization/en-US/",
"paths": [
"toolkit/updates/history.ftl",
"security/certificates/deviceManager.ftl",
"security/certificates/certManager.ftl",
]
},
];
function messageFromBundle(bundle, errors, message, args) {
const formatted = {
value: null,
attributes: null,
};
if (message.value) {
formatted.value = bundle.formatPattern(message.value, args, errors);
}
let attrNames = Object.keys(message.attributes);
if (attrNames.length > 0) {
formatted.attributes = new Array(attrNames.length);
for (let [i, name] of attrNames.entries()) {
let value = bundle.formatPattern(message.attributes[name], args, errors);
formatted.attributes[i] = {name, value};
}
}
return formatted;
}
async function testParsing({FluentBundle, FluentResource}) {
console.log(`Test for idlBacked: ${idlBacked}.`);
let ftls = [];
for (let {prefix, paths} of sources) {
for (let path of paths) {
ftls.push(await fetch(`${prefix}${path}`).then(res => res.text()));
}
}
performance.mark("fluent-parse-start");
let parseStart = performance.now();
let resources = ftls.map((ftl) => {
return new FluentResource(ftl);
});
let bundle = new FluentBundle(["en-US"]);
for (let res of resources) {
bundle.addResource(res);
}
let parseEnd = performance.now();
performance.mark("fluent-parse-end");
console.log(`perf(parse): ${parseEnd-parseStart}`);
}
async function testResolving({FluentBundle, FluentResource}) {
console.log(`Test for idlBacked: ${idlBacked}.`);
let ftls = [];
for (let {prefix, paths} of sources) {
for (let path of paths) {
ftls.push(await fetch(`${prefix}${path}`).then(res => res.text()));
}
}
performance.mark("fluent-parse-start");
let parseStart = performance.now();
let resources = ftls.map((ftl) => {
return new FluentResource(ftl);
});
let bundle = new FluentBundle(["en-US"]);
for (let res of resources) {
bundle.addResource(res);
}
let parseEnd = performance.now();
performance.mark("fluent-parse-end");
console.log(`perf(parse): ${parseEnd-parseStart}`);
let l10nElements = Array.from(document.querySelectorAll("[data-l10n-id]")).map(elem => document.l10n.getAttributes(elem));
let values = [];
performance.mark("fluent-resolve-start");
let resolveStart = performance.now();
let errors = [];
for (let elem of l10nElements) {
let msg = bundle.getMessage(elem.id);
values.push(messageFromBundle(bundle, errors, msg, elem.args));
}
let resolveEnd = performance.now();
performance.mark("fluent-resolve-end");
console.log(`perf(resolve): ${resolveEnd-resolveStart}`);
}
let test = includeResolving ? testResolving : testParsing;
test(idlBacked ? { FluentBundle, FluentResource } : ChromeUtils.import("resource://gre/modules/Fluent.jsm"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment