i have a directory that contains small XML files (every file is 170~200 bytes), and i want to read all content of every file and merge them in a single XML file, displayed in a tree.
OLD
FileUtils.File + NetUtil.asyncFetch + NetUtil.readInputStreamToString
Time to read 3000 XML files 1112.3642930000005 msec
NEW
OS.File.DirectoryIterator + OS.File.read
Time to read 3000 XML files 5330.708094999999 msec
I noticed an enormous difference in the reading time per single file : OLD has a time of 0.08~0.12 msec NEW has a time 0.5~6.0 msec ( 6.0 it's not a typo i saw some time peaks, in comparison to the OLD)
I know that the OLD one is linked to C++ but at : https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm
OS.File is a new API designed for efficient, off-main thread, manipulation of files by privileged JavaScript code.
I don't see the efficency of the NEW API. Is there something wrong in my code?
n.b : dbgPerf is a performance debug that collects time and a comment in an object array and performs all calculation when i call the end function at the end of all. it does not affect performance.
Code using nsIFile :
this._readDir2 = function (pathToTarget, callbackEndLoad) {
var _content = '';
dbgPerf.add("2 start read dir");
var fuDir = new FileUtils.File(pathToTarget);
var entries = fuDir.directoryEntries;
var files = [];
while (entries.hasMoreElements()) {
var entry = entries.getNext();
entry = entry.QueryInterface(OX.LIB.Ci.nsIFile);
if (entry.isFile()) {
var channel = NetUtil.newChannel(entry);
files.push(channel);
dbgPerf.add("ADD file" + entry.path);
} else {
dbgPerf.add("NOT a file" + entry.path);
}
}
var totalFiles = files.length;
var totalFetched = 0;
for (var a = 0; a < files.length; a++) {
var entry = files[a];
dbgPerf.add("start asynch file " + entry.name);
NetUtil.asyncFetch(entry, function (inputStream, status) {
totalFetched++;
if (!Components.isSuccessCode(status)) {
dbgPerf.add('asyncFetch failed for reason ' + status);
return;
} else {
_content += NetUtil.readInputStreamToString(inputStream, inputStream.available());
dbgPerf.add("process end file " + entry.name);
}
if (totalFetched == files.length) {
var parser = new DOMParser();
_content = _content.replace(/<root>/g, '');
_content = _content.replace(/<\/root>/g, '');
_content = _content.replace(/<catalog>/g, '');
_content = _content.replace(/<\/catalog>/g, '');
_content = _content.replace(/<\?xml[\s\S]*?\?>/g, '');
xmlDoc = parser.parseFromString('<?xml version="1.0" encoding="utf-8"?><root>' + _content + '</root>', "text/xml");
//dbgPerf.add("2 fine parsing XML file " + arrFileData);
var response = {};
response.total = totalFiles;
response.xml = xmlDoc;
callbackEndLoad(response);
}
});
}
dbgPerf.add("2 AFTER REQUEST ALL FILE");
};
CODE USING OS.File :
this._readDir = function (pathToTarget, callbackEndLoad) {
dbgPerf.add("1 inizio read dir");
var xmlDoc;
var arrFileData = '';
var iterator = new OS.File.DirectoryIterator(pathToTarget);
var files = [];
iterator.forEach(function onEntry(entry) {
if (!entry.isDir) {
files.push(entry.path);
}
});
var totalFetched = 0;
files.forEach(function (fpath) {
Task.spawn(function () {
arrFileData += OS.File.read(fpath, {
encoding: "utf-8"
});
totalFetched++;
if (totalFetched == files.length) {
var parser = new DOMParser();
arrFileData = arrFileData.replace(/<root>/g, '');
arrFileData = arrFileData.replace(/<\/root>/g, '');
arrFileData = arrFileData.replace(/<catalog>/g, '');
arrFileData = arrFileData.replace(/<\/catalog>/g, '');
arrFileData = arrFileData.replace(/<\?xml[\s\S]*?\?>/g, '');
xmlDoc = parser.parseFromString('<?xml version="1.0" encoding="utf-8"?><root>' + arrFileData + '</root>', "text/xml");
dbgPerf.add("1 fine parsing XML file " + arrFileData);
var response = {};
response.xml = xmlDoc;
callbackEndLoad(response);
}
});
});
};