closures vs eval scope passage

JavaScript performance comparison

Test case created by Shimon Doodkin and last updated

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.

Testing in unknown unknown
Test Ops/sec
hand typed
test1()
pending…
closure and for
test2()
pending…
replaced evaled
test3()
pending…
replaced evaled and copied to courrent scope-works
test4()
pending…
replaced evaled and copied to courrent scope with a function dating bak to evaled scope
test5()
pending…
see if i all together possible
test6()
pending…
see if i all together possible2 -works
test7()
pending…
see if i all together possible3 -works
test8()
pending…
see if i all together possible4 -works
test9()
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:

0 comments

Add a comment