[英]Javascript code too slow in Firefox extension using Storage service
我在 firefox 擴展中運行以下 javascript 代碼
highlightLinks: function(e) {
var anchors = e.target.getElementsByTagName("a");
let file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file.append("test.sqlite");
var storageService = Components.classes["@mozilla.org/storage/service;1"]
.getService(Components.interfaces.mozIStorageService);
var conn = storageService.openDatabase(file);
for (var i = 0; i < anchors.length; i++) {
var statement = conn.createStatement("select * from links where url=?1");
statement.bindStringParameter(0, anchors[i].href);
var visited = false;
try {
while (statement.executeStep()) {
visited = true;
break;
}
} catch (e) {
} finally {
statement.reset();
}
statement.finalize();
if (visited) {
anchors[i].innerHTML += "+";
}
}
conn.close();
},
這個 function 在 DOMContentLoaded 事件上運行。 它檢查頁面上的每個鏈接是否存在於test.sqlite
數據庫中並標記存在的鏈接。
問題是現在頁面的加載速度要慢得多(尤其是當我降低 CPU 頻率時)。 你能幫我提高這段代碼的效率和節省資源嗎?
編輯:通過刪除 function 和的事件偵聽器,實現了顯着的加速。
謝謝你
如果您將createStatement
拉出循環並重用它,每次都重新綁定參數,它會更快。 存儲文檔說:“注意:如果您需要多次執行一條語句,緩存 createStatement 的結果會給您帶來顯着的性能提升,因為 SQL 查詢不需要每次都解析。”
所以而不是:
for (var i = 0; i < anchors.length; i++) {
var statement = conn.createStatement("select * from links where url=?1");
statement.bindStringParameter(0, anchors[i].href);
// ... do stuff with results
寫:
var statement = conn.createStatement("select * from links where url=?1");
for (var i = 0; i < anchors.length; i++) {
statement.bindStringParameter(0, anchors[i].href);
// ... do stuff with results
編輯:另外,如果您使用的是最近的 Firefox,您可以使用他們的異步 API 以避免延遲 UI。 不要調用executeStep
,而是使用executeAsync 。
statement.executeAsync({
handleResult: function(aResultSet) {
// ... do stuff with results
},
handleError: function(aError) {
print("Error: " + aError.message);
},
handleCompletion: function(aReason) {
if (aReason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED)
print("Query canceled or aborted!");
}
});
第一個提示,雖然不會節省太多時間,但在 for 循環的條件下不使用 anchors.length。 更好的使用:
for(var i = 0, num = anchors.length; i < num, i++) {...}
通常,當您調用數據庫(而不是瀏覽器的數據庫)時,最好進行一次調用,將所需的所有數據獲取到數組或 hash 中,然后在內部使用它們。
編輯:
我會這樣做:從存儲中加載所有鏈接並構建 hash ,例如:
linksHash = {
'url-1':true,
...,
'url-n':true
}
然后循環anchors
並使用以下內容進行檢查:
if(linksHash[anchors[i].href]){
//the link href is in the hash
}
然后,如果您注意到 RAM 成為問題,請將表的負載分成 2 塊或更多塊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.