Comparison of module method declarations

Posted on
  • I find some of this info in other posts, but not a direct comparison. I'm curious as to the trades of speed and size efficiency, "public" (exposed) vs "private" (not exposed), and any other pros or cons of various ways of defining methods relative to Espruino. For example, consider the module...

    // Foo.js: module methods examples...
    
    function barNone() {
      return 0;
      };
    
    function bar(n) {
      return n;
      };
    
    function bar2(n) {
      return n*n;
      };
      
    function Foo(){
      this.bar = bar;
      };
    
    Foo.prototype.bar2 = bar2;
    
    Foo.prototype.bar3 = function bar3(n) {
      n = n || barNone();
      return n*n*n;
      };
    
    exports = Foo
    

    And the text case use ...

    // FooBar.js: test of Foo.js module...
    
    var foo = new (require("Foo"))();
    
    console.log("foo",foo);
    console.log("foo.bar(4)",foo.bar(4));
    console.log("foo.bar2(4)",foo.bar2(4));
    console.log("foo.bar3(4)",foo.bar3(4));
    console.log("foo.bar3()",foo.bar3());
    

    Which produces the output...

    foo {
      "bar": function (a) {return a;}
     }
    foo.bar(4) 4
    foo.bar2(4) 16
    foo.bar3(4) 64
    foo.bar3() 0
    

    I'm sure one could come up with other method notions given the "rich" flexibility of JavaScript, but for starters I'd like to know which one of these declarations makes better sense and why.

    The barNone declaration is not visible or usable outside the module, but the others are. The bar declaration is explicitly exposed to the user and makes for a more verbose listing of foo, but appears to minimize better. It would also seem to be faster as the object does not need to look down the prototype chain. However, this approach does not seem to be used. Is there some other downside, for example scope or code replication with additional "new" foo objects. And the prototype declarations are not explicitly visible, but still exposed to the user. What other reasons would you chose one way over another?

  • If you're using objects I'd say bar3 is probably best - but if you don't need any state then just export functions rather than a whole object.

    If you do:

    function Foo(){
      this.bar = bar;
      };
    

    then even once initialised, Espruino will still contain this.bar = bar;, which would be wasting some memory.

    The important thing to remember is that Espruino actually executes the module code at the time it is uploaded, so:

    function Foo() {
    }
    
    Foo.prototype.bar = function() {
    };
    

    Is executed, and you end up with effectively:

    var Foo = {
      prototype : {
       bar : function() {}
      }
    };
    

    So it doesn't actually matter if you manage to take few bytes off the minified module. What matters is the amount of memory that's used (process.memory().usage) after the module has been uploaded - and for that, you want the minimum amount of 'boilerplate' code inside functions.

  • Another example is:

    exports.a=[1,2,3,....,100];
    exports.b=new Uint8Array([1,2,3,....,100]);
    

    So a minifies to be smaller, but in reality b uses drastically less memory, because it's not the definition that matters, but how much space it takes up once executed.

  • Makes sense. When you say "actually executes the module" does it really execute or does it enterpret to prep for execution? Does the same apply to code loaded outside a module at the main script?

  • It really does execute the code. For example:

    var a = [];
    for (var i=0;i<100;i++)a[i]=i;
    

    will create a 100 element array called a after it is uploaded.

    However functions (and what is in them) won't be executed (unless you explicitly execute them). So:

    function foo() {
      var a = [];  
      for (var i=0;i<100;i++)a[i]=i;
      return a;
    }
    

    won't create an array. All that is stored is some data representing the function, and the source code inside it.

    It might be worth taking a look at this: http://www.espruino.com/Performance

  • @Gordon

    Looking at your link above lead me to here: http://www.espruino.com/Compilation

    This only works for the arm boards right?

  • Yeah... Potentially someone could host their own compiler, but it could be quite difficult. You need to be able to make self-contained position independent code, which required some trial and error with compiler flagsd (at least for me).

  • However I should point out that compiling your code does not make it smaller. In fact it usually drastically increases the size.

    Minified JS code is actually extremely efficient, so the only reason you'd use compiled code is for the speed benefit - and you only really get that for code that does a lot of integer work.

  • Thanks. I've been looking at the size of the FlashStore modules I've made. It looks like you can gain quite a bit by shorting variable names I.e, address -> addr and shorting up internal this.xxx vars.
    It also uses child objects pointing to a parent, so I'm wondering if a single class that is both will reduce the overall code size considerably, as its 2000 byes for both the flashItem and FlashStore modules (not fully minimized yet)

    http://forum.espruino.com/conversations/­283045/

  • Thanks. I have looked at Performance page, Compilation, Inline Assembler, and other related documentation, but it took a couple more examples to sink in. When you said execute, I was confused by the exact example you showed above where the function would not be executed until actually called. This has helped a bunch.

  • No problem. I'll see if I can stick that example into one of those pages.

  • @CanyonCasa, take a look at this and this post. It may give you some understanding what is processed and what not and the major difference to other MC technologies, such as Arduino. Your particular code and the module code are treated the same way: as it streams into Espruino - either by entering in the console or by uploading from the editor pane or as it happens with referenced modules that get loaded from the module Web or SDCard - the code is processed and placed in Espruino's RAM.

  • @allObjects thanks. You know I read that Espruino runs code on upload a couple times, but so used to conventional compiled code mindset it didn't sink in.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Comparison of module method declarations

Posted by Avatar for CanyonCasa @CanyonCasa

Actions