patternjavascriptMinor
Using Javascript FileWriter with minimal use of closures
Viewed 0 times
javascriptwithfilewriterusingminimaluseclosures
Problem
I'm currently writing a WebGL HTML5 game, and large part of the game initialization involved loading assets streamed over a websocket, and saving them to disk using the FileSystem API.
As part of optimizing the code, we're trying to eliminate as many memory allocations as we can, which means cutting down on the use of closures, object/array creation during the main game loop and so on.
One of the biggest uses of closures left is our interaction with the FileSystem API, namely the part where we write the assets to disk:
As you can see, this code involves the creation of something like six new closures for every file write, which isn't the greatest when we're trying to cut down on memory allocation.
I initially tried to pull each of the closures out into standalone functions, but obvi
As part of optimizing the code, we're trying to eliminate as many memory allocations as we can, which means cutting down on the use of closures, object/array creation during the main game loop and so on.
One of the biggest uses of closures left is our interaction with the FileSystem API, namely the part where we write the assets to disk:
//Write file to disk
directory.getFile(
filename,
CREATE_TRUE,
function(fileEntry) {
fileEntry.createWriter(
function(fileWriter) {
fileWriter.onwriteend=function(e) {
finishedRequest(filename);
if (onSuccess!==undefined) onSuccess(filename);
};
fileWriter.onerror=function(e) {
finishedRequest(filename);
if (onError!==undefined) onError(filename, "Write error: "+directoryRoot+"/"+filename);
};
var dataBlob=new Blob([new Uint8Array(data)]);
if (append) fileWriter.seek(fileWriter.length);
fileWriter.write(dataBlob,"application/octet-stream");
},
function(e) {
finishedRequest(filename);
if (onError!==undefined) onError(filename,"File writer creation error: "+directoryRoot+"/"+filename:"");
}
);
},
function(e) {
finishedRequest(filename);
if (onError!==undefined) onError(filename,DEVELOPMENT_MODE?"File not found: "+directoryRoot+"/"+filename:"");
}
);As you can see, this code involves the creation of something like six new closures for every file write, which isn't the greatest when we're trying to cut down on memory allocation.
I initially tried to pull each of the closures out into standalone functions, but obvi
Solution
I think that you will always need some closures, but you can limit what they carry.
This was your example:
I guess that your intention was to define a function for each case and then assign it.
So your example transforms into this (I'm just reorganizing your code and fixing a function declaration).
This is actually an optimization because you can reuse things, the problem now is how do we get the filename. Well you can write a function that gets the filename and return a new function that only has the filename in its closure and nothing else. Like this:
Note that this way you just pass what you need, variables, functions but always controlling the closure "size".
Hope it helps you, good luck with the game!
This was your example:
...
fileWriter.onwriteend=onFileWrite;
...
function onFileWrite=function(e) {
finishedRequest(filename); //filename needs to be retrieved from somewhere...
if (onSuccess!==undefined) onSuccess(filename);
}I guess that your intention was to define a function for each case and then assign it.
So your example transforms into this (I'm just reorganizing your code and fixing a function declaration).
var onFileWrite = function(e) {
finishedRequest(filename); //filename needs to be retrieved from somewhere...
if (onSuccess!==undefined) onSuccess(filename);
}
...
fileWriter.onwriteend=onFileWrite;
...This is actually an optimization because you can reuse things, the problem now is how do we get the filename. Well you can write a function that gets the filename and return a new function that only has the filename in its closure and nothing else. Like this:
var onFileWrite = function(filename) {
return function(e) {
finishedRequest(filename);
if (onSuccess!==undefined) onSuccess(filename);
}
}
...
fileWriter.onwriteend=onFileWrite(filename);
...Note that this way you just pass what you need, variables, functions but always controlling the closure "size".
Hope it helps you, good luck with the game!
Code Snippets
...
fileWriter.onwriteend=onFileWrite;
...
function onFileWrite=function(e) {
finishedRequest(filename); //filename needs to be retrieved from somewhere...
if (onSuccess!==undefined) onSuccess(filename);
}var onFileWrite = function(e) {
finishedRequest(filename); //filename needs to be retrieved from somewhere...
if (onSuccess!==undefined) onSuccess(filename);
}
...
fileWriter.onwriteend=onFileWrite;
...var onFileWrite = function(filename) {
return function(e) {
finishedRequest(filename);
if (onSuccess!==undefined) onSuccess(filename);
}
}
...
fileWriter.onwriteend=onFileWrite(filename);
...Context
StackExchange Code Review Q#23809, answer score: 2
Revisions (0)
No revisions yet.