问题
I installed iOS 8 on a third generation iPad and tried IndexedDB in Safari. My sample code just adds 1000 objects to an object store.
It works however it is very slow compared to other devices with similar or weaker hardware.
See this snippet for implementation details (IndexedDB seems to be disabled on stackoverflow so the example does not work out of the box - use this fiddle instead):
Added the snippet to jsbin because jsfiddle raises a SecurityException on iOS device and updated with Deni Spasovskis answer http://jsbin.com/jorohe/1/. The problem still persists.
Original code:
var openRequest = window.indexedDB.open("testdb");
openRequest.onsuccess = function (event) {
document.getElementById("output").innerHTML += "open success<br/>";
var db = event.target.result;
var trans = db.transaction(["testStore"], (typeof IDBTransaction.READ_ONLY !== "undefined") ? IDBTransaction.READ_WRITE : "readwrite" );
var store = trans.objectStore("testStore");
var reqClear = store.clear();
reqClear.onsuccess = function () {
var objectsToAdd = 1000;
var addedObjects = 0;
var startTime = window.performance.now();
for (var i=0; i<objectsToAdd; i++) {
(function (pos) {
var req = store.add({testID: pos, a: "foo", b: "bar"});
req.onsuccess = function () {
addedObjects++;
if (addedObjects >= objectsToAdd) {
document.getElementById("output").innerHTML += "done adding<br />";
document.getElementById("output").innerHTML += "Took: "+(window.performance.now() - startTime)+"ms<br />";
}
}
req.onerror = function () {
document.getElementById("output").innerHTML += "error adding element:" + req.error + " <br/>";
}
})(i);
}
}
reqClear.onerror = function () {
document.getElementById("output").innerHTML += "error clearing store: "+reqClear.error+"<br/>";
}
};
openRequest.onupgradeneeded = function (event) {
var db = event.target.result;
var objectStore = db.createObjectStore("testStore", { keyPath: "testID" });
document.getElementById("output").innerHTML += "created store<br/>";
};
openRequest.onerror = openRequest.onabort = function () {
document.getElementById("output").innerHTML += "error opening db<br/>";
}
<div id="output">
</div>
The iPad took around 6 seconds while Internet Explorer on a HTC Windows Phone 8s (weaker hardware) only took 1,5 seconds and Chrome on a Samsung Galaxy S III (which might be comparable to the iPad) finished the insert in 300 milliseconds.
While I understand that this technology is new on iOS I was not expecting such a harsh performance decrease.
Is there anything wrong with the code or is there any other way to achieve decent performance with IndexedDB on iOS devices?
回答1:
For optimal performance when batch inserting you shouldn't listen for events on every add statement, instead you should attach to the transaction oncomplete
and onerror
events.
I've changed your code a bit and got 15% performance increase (~290ms down from ~340ms) on my phone (nexus 4). But this is still slow when compared to the PC.
The code snippet doesn't work so here is link to the jsFiddle: http://jsfiddle.net/a5p6mL6m/2/
var openRequest = window.indexedDB.open("testdb");
openRequest.onsuccess = function (event) {
document.getElementById("output").innerHTML += "open success<br/>";
var db = event.target.result;
var trans = db.transaction(["testStore"], (typeof IDBTransaction.READ_ONLY !== "undefined") ? IDBTransaction.READ_WRITE : "readwrite" );
var store = trans.objectStore("testStore");
var startTime;
trans.oncomplete = function () {
document.getElementById("output").innerHTML += "finished adding<br />";
document.getElementById("output").innerHTML += "End time: "+(window.performance.now() - startTime)+"<br />";
}
var reqClear = store.clear();
reqClear.onsuccess = function () {
startTime = window.performance.now();
var objectsToAdd = 1000;
var addedObjects = 0;
for (var i=0; i<objectsToAdd; i++) {
store.add({testID: i, a: "foo", b: "bar"});
}
}
reqClear.onerror = function () {
document.getElementById("output").innerHTML += "error clearing store: "+reqClear.error+"<br/>";
}
};
openRequest.onupgradeneeded = function (event) {
var db = event.target.result;
var objectStore = db.createObjectStore("testStore", { keyPath: "testID" });
document.getElementById("output").innerHTML += "created store<br/>";
};
openRequest.onerror = openRequest.onabort = function () {
document.getElementById("output").innerHTML += "error opening db<br/>";
}
<div id="output">
</div>
来源:https://stackoverflow.com/questions/25914265/indexeddb-slow-when-inserting