#javascript #firefox #firefox-addon #firefox-addon-restartless
#javascript #firefox #firefox-addon #firefox-addon-restartless
Вопрос:
Определенная информация передается в restartless addon
function startup(data, reason) { }
data = {
id: "***********",
version: "1.0",
installPath: XPCWrappedNative_NoHelper, // nsIFile
resourceURI: XPCWrappedNative_NoHelper, // nsIURI
oldVersion: "1.0"
};
Являются ли приведенные выше единственными доступными данными?
Возможно ли получить имя аддона без доступа к AddonManager?
Мой опыт работы с AddonManager.jsm показал, что он громоздкий и медленный.[1]
В случае, если приведенные выше данные являются единственными доступными, каков наилучший способ получить nsIURI для install.rdf в restartless addons (для доступа с помощью XHR)?
В оверлейных аддонах я добавляю resource
ссылку, указывающую на install.rdf. Однако resource
он недоступен в restartless addons, и установка следующего нежелательна
content addon ./
[1] Обновление: уточнение / исправление:
Временная выборка XHR не включала синтаксический анализ XML и извлечение данных. Поэтому общая операция (XHR, обратный вызов, responseXML, захват данных) займет гораздо больше времени.
Ответ №1:
Являются ли приведенные выше единственными доступными данными?
Да, по-видимому. Документация, кстати.
Возможно ли получить имя аддона без доступа к AddonManager?
Нет. (Ну, вы говорите о разборе install.rdf
самостоятельно, что было бы возможно, но ИМХО дерьмовый. AddonManager
является ли поддерживаемым и рекомендуемым способом; например, рассмотрим угловые случаи метаданных, например, метаданные вкл. возможно, имя было обновлено из онлайн-источника).
Мой опыт работы с AddonManager.jsm доказал, что он громоздкий и медленный. Например, асинхронный анализ install.rdf с помощью XHR занимает около 1 мс, в то время как получение тех же данных через AddonManager.jsm занимает 160-170 мс. Это в 160-170 раз медленнее.
Честно говоря, я сомневаюсь в ваших цифрах. 1ms
XHR ?! Даже настройка XHR занимает больше времени, и даже если XPI (или flat install.rdf
) уже кэширован внутри или, по крайней мере, в кэше диска ОС, ввод-вывод займет больше времени, даже если вы не проанализировали его как XML и не выполнили регулярное выражение из того, что вам нужно из текстового содержимого.
Кроме того, обратите внимание, что AddonManager
необязательно инициализировать базу данных метаданных при вызове вашего startup()
метода. Вызов любого AddonManager
метода запроса на этом этапе приведет к принудительной инициализации один раз, что означает, что первый вызов может быть немного медленным.
В общем, вы не должны запрашивать какие-либо данные, например, имя дополнения, пока оно вам действительно не понадобится, в частности, во время запуска.
В случае, если приведенные выше данные являются единственными доступными, каков наилучший способ получить nsIURI для install.rdf в restartless addons (для доступа с помощью XHR)?
Использование __SCRIPT_URI_SPEC__
или data.resourceURI
:
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
// Using proper URI parsing
let selfURI = Services.io.newURI(__SCRIPT_URI_SPEC__, null, null);
let installRDF = Services.io.newURI("install.rdf", null, selfURI).spec;
Cu.reportError(installRDF);
// Or using string manipulation
let baseURISPEC = __SCRIPT_URI_SPEC__.substr(
0,
__SCRIPT_URI_SPEC__.length - "bootstrap.js".length
);
let installRDF2 = baseURISPEC "install.rdf";
Cu.reportError(installRDF2);
Cu.reportError((installRDF == installRDF2).toString()); // true
let installRDF = Services.io.newURI("install.rdf", null, selfURI).spec;
Cu.reportError(installRDF);
function startup(data) {
// Or using bootstrap data
let installRDF3 =
Services.io.newURI("install.rdf", null, data.resourceURI).spec;
Cu.reportError(installRDF3);
Cu.reportError((installRDF == installRDF3).toString()); // true
}
__SCRIPT_URI_SPEC__
преимущество в том, что оно доступно немедленно, а не только в методах точки входа.
Редактировать Мне стало любопытно, и время пришло.
[LOG] AM: 177, 18, 1, 1, 0, 0, 0, 0, 0, 1
[LOG] AM: avg 0.4
[LOG] AM: 168, 18, 1, 0, 0, 1, 0, 0, 0, 0
[LOG] AM: avg 0.3
[LOG] AM: 169, 21, 1, 0, 1, 0, 0, 0, 0, 0
[LOG] AM: avg 0.3
[LOG] XX: 160, 25, 25, 4, 1, 2, 2, 3, 1, 1
[LOG] XX: avg 30.9
[LOG] XX: 137, 20, 19, 4, 1, 2, 3, 2, 0, 1
[LOG] XX: avg 26.0
[LOG] XX: 145, 22, 25, 3, 2, 2, 2, 2, 1, 1
[LOG] XX: avg 25.1
Получается, что XHR не совсем быстрее. Немного при первом доступе, немного хуже при некоторых последующих запусках (это можно объяснить тем, что это несколько затратно и выполняется во время запуска, когда много других вещей также потребляют ресурсы), и после этого разница незначительна. Но с XHR вам все равно нужно получить имя из DOM, в то время как с AM это просто addon.name
.
Вот мой глупый микро-бенчмарк:
const {classes: Cc, interfaces: Ci, utils: Cu, Constructor: CC} = Components;
Cu.import("resource://gre/modules/Services.jsm");
// Using proper URI parsing
let selfURI = Services.io.newURI(__SCRIPT_URI_SPEC__, null, null);
let installRDF = Services.io.newURI("install.rdf", null, selfURI).spec;
Cu.reportError(installRDF);
const XMLHttpRequest =
CC("@mozilla.org/xmlextras/xmlhttprequest;1", "nsIXMLHttpRequest");
function log(s) {
dump("[LOG] " s "n");
}
function print(name, diffs) {
log(name ": " diffs.join(", "));
// Average, disregarding single best, and two worst
diffs.sort();
diffs.shift();
diffs.pop();
diffs.pop();
let avg = diffs.reduce((c,p) => c p, 0) / diffs.length;
log(name ": avg " avg.toFixed(1));
}
function timeAM(id) {
Cu.import("resource://gre/modules/AddonManager.jsm");
let diffs = [];
var run = function(x) {
x = x || 0;
let start = Date.now();
AddonManager.getAddonByID(id, function(addon) {
let d = Date.now() - start;
diffs.push(d);
if ( x == 10) {
print("AM", diffs);
return;
}
run(x);
});
};
run();
}
function timeXHRXML() {
Cu.import("resource://gre/modules/AddonManager.jsm");
let diffs = [];
let run = function(x) {
x = x || 0;
let start = Date.now();
let r = new XMLHttpRequest();
r.overrideMimeType("text/xml");
r.open("GET", installRDF);
r.onloadend = function() {
let d = Date.now() - start;
diffs.push(d);
if ( x == 10) {
print("XX", diffs);
return;
}
run(x);
};
r.send();
};
run();
}
function startup(data) {
Cu.reportError("in");
//timeAM(data.id);
timeXHRXML(data.id);
}
Комментарии:
1. Спасибо, Nils, за тест производительности. Я удалил данные синхронизации из своего сообщения.