closures vs eval scope passage
JavaScript performance comparison
Info
while i was looking for a ways to initialize data modules
in v8 javascript engine there is scope.close() when you develop v8 native modules. it happens at each end of function to let pass variables on while maintaining scope. also when you do eval it makes like a new file.js with evaled code and append it to running code
suppose a simple function that should be dynamically constructed for different tables and i wanted to have same performance in dynamic as in hand typed.
will it run faster with closures or with evaled function
app.put('/api/users/:id', function(req, res)
{
var data = req.body;
db.query(
'UPDATE users '+
'SET username = ?, password = ? where _id = ?',
[data.username , data.password, req.params.id],
function(err, results, fields) {
var insertId = results.insertId
data._id = insertId;
res.send(JSON.stringify(data));
}
);
});
conclusions:
to get fast execution put all code in one js file
it is worth it after doing eval to copy functions to local scope
it is good only if it copied totally, if there is even a one function or a variable dating back to another scope it slows down twice.
also it is good only if the code evaled in the same scope otherwise it slows down
test 4 and test 8 actually work
Preparation code
<script>
Benchmark.prototype.setup = function() {
function query()
{
return Math.random();
}
function test1()
{
var data={username:'aaa',password:'vvv',_id:1}
query(
'UPDATE users '+
'SET username = ?, password = ? where _id = ?',
[data.username , data.password, 1],
function(err, results, fields) {
}
);
}
var closureargs=['myusername','mypassword','_id']
var q=''
for(var i=0;i<closureargs.length;i++)
{
q+=(q!=''?',':'')+closureargs[i]+' = ?'
}
function test2()
{
var data={username:'aaa',password:'vvv',_id:1}
var s=[]
for(var i=0;i<closureargs.length;i++)
{
s[i]=data[closureargs[i]];
}
query(
'UPDATE users '+
'SET '+q,
s,
function(err, results, fields) {
}
);
}
function strreplacefn(fn,replacefromtoarr)
{
var s=fn.toString();
for(var i=0;i<replacefromtoarr.length;i++)
{
s=s.split(replacefromtoarr[i][0]).join(replacefromtoarr[i][1]);
}
return s;
}
//replace something whatether and make new function from eval
eval(strreplacefn(test1,[['function '+test1.name+'(','function test3('],
['username','myusername'],
['password','mypassword']]))
var test4=test3;
//try adding a function dating back to evaled scope
eval('function piggyback_fn(){return Math.random();};'+
strreplacefn(test1,[['function '+test1.name+'(','function test5_('],
['username','myusername'],
['password','mypassword'],
['query(','piggyback_fn();query(']
]))
var test5=test5_;
//try to make a function that does all together
function strreplacefn1(fn,replacefromtoarr,optnewname)
{
var s=fn.toString();
//optnewname=optnewname||fn.name||'fn'
optnewname='fn'
replacefromtoarr.push(['function '+fn.name+'(','function '+optnewname+'('])
for(var i=0;i<replacefromtoarr.length;i++)
{
s=s.split(replacefromtoarr[i][0]).join(replacefromtoarr[i][1]);
}
eval(s)
//return {fn:eval(optnewname)};
return fn;
}
var test6=strreplacefn1(test1,[['username','myusername'],
['password','mypassword']])
//try to make a function that does all together2
function strreplacefn2(fn,replacefromtoarr,optnewname)
{
var s=fn.toString();
optnewname=optnewname||fn.name||'fn'
//optnewname='fn'
replacefromtoarr.push(['function '+fn.name+'(','function '+optnewname+'('])
for(var i=0;i<replacefromtoarr.length;i++)
{
s=s.split(replacefromtoarr[i][0]).join(replacefromtoarr[i][1]);
}
return s+';'+optnewname;
}
var test7=eval(strreplacefn2(test1,[['username','myusername'],
['password','mypassword']],'test7_'));
//try to make a function that does all together3
function strreplacefn3(fn,replacefromtoarr,optnewname)
{
var s=fn.toString();
optnewname=optnewname||fn.name||'fn'
//optnewname='fn'
replacefromtoarr.push(['function '+fn.name+'(','function '+optnewname+'('])
for(var i=0;i<replacefromtoarr.length;i++)
{
s=s.split(replacefromtoarr[i][0]).join(replacefromtoarr[i][1]);
}
return s;
}
eval(strreplacefn3(test1,[['username','myusername'],
['password','mypassword']],'test8'));
var test8=test8;// copy to current scope
var test9=eval(strreplacefn2(test1,[['username','myusername'],
['password','mypassword']],'test9'));
//warm up
for(var i=0;i<500;i++)
{
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
}
};
</script>
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
hand typed |
|
pending… |
closure and for |
|
pending… |
replaced evaled |
|
pending… |
replaced evaled and copied to courrent scope-works |
|
pending… |
replaced evaled and copied to courrent scope with a function dating bak to evaled scope |
|
pending… |
see if i all together possible |
|
pending… |
see if i all together possible2 -works |
|
pending… |
see if i all together possible3 -works |
|
pending… |
see if i all together possible4 -works |
|
pending… |
Compare results of other browsers
Revisions
You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:
- Revision 1: published by Shimon Doodkin and last updated
- Revision 2: published by Shimon Doodkin
0 comments