Problem with E.toString

Posted on
  • Here is the test code

    //xtest.js 26 Jan2018
    // trying this on a Pico
    //try changing the value of chk
    
    var n =100, chk=23*1024;
    var tdata=new Uint8Array(chk);
    var i;
    for(i=0;i<1024;i++){
      tdata[i]=0x30;
      tdata[i+1024]=0x31;
    }//next i
    
    function xsend(a){console.log(n,a.length);}
    
    function test(){
    while (n){
      xsend(E.toString(tdata));
      n--;
    }
    }//end test
    
    
    test();
    

    Here is the output

     1v95 Copyright 2017 G.Williams
    >100 23552
    99 23552
    98 23552
    97 23552
    Uncaught Error: Field or method "length" does not already exist, and can't create it on undefined
     at line 13 col 16
    console.log(n,a.length);
                   ^
    in function "xsend" called from line 17 col 26
      xsend(E.toString(tdata));
                             ^
    in function "test" called from line 1 col 6
    test();
         ^
    =undefined
    >
    

    Similar problem on ESP8266 running Espruino, but different array sizes to get it to run at all.

  • Trying process.memory to attempt a debug

    //xtest2.js 27 Jan2018
    // trying this on a Pico
    //try changing the value of chk
    
    // process.memory uncommented =PM
    // comment out process.memory =NPM
    ///
    // chk=1*1024 works both cases
    // chk =2*1024 works with PM,fails NPM
    // chk=25*1024 works with PM, fails NPM
    // chk=26*1024 fails just too big
    var n =100, chk=25*1024; 
    var tdata=new Uint8Array(chk);
    
    function xsend(a){
      console.log(n,a.length);
    //  process.memory();// this makes it work
    }//end xsend
    
    function test(){
    var a;
    while (n){
      xsend(E.toString(tdata)); //fails if no process.memory
      n--;
    }
    }//end test
    
    setTimeout(function () {
     test();
    }, 1000);
    

    The process.memory() fixes the bug.

     1v95 Copyright 2017 G.Williams
    >
    =undefined
    100 25600
    99 25600
    98 25600
    97 25600
    Uncaught Error: Field or method "length" does not already exist, and can't create it on undefined
     at line 16 col 16
    console.log(n,a.length);
                   ^
    in function "xsend" called from line 23 col 26
      xsend(E.toString(tdata)); //fails if no process.memory
                             ^
    in function "test" called from line 1 col 6
    test();
         ^
    in function called from system
    > 
    
  • You are creating a 23k string. That is quite large in espruino world!

    The esp8266'has even less resources, so try changing the 23 to 4 and see if it works!

  • The example above is on a Pico.
    It is an attempt to zero in on the bug first found in the following code.

    For the ESP8266 -01 try this code

    //WSDesp8266A/js 27Jan2018
    // using process.memory to fix bug
    
    //http//192.168.1.6:8080
    //ESP8266 with Espruino flahed
    
    
    // list of Wifi and passwords
    var SSID="ssid";
    var key="keykey";
    var Startagain=0;
    var myinterval;
    
    var n =100, chk=2*1024;
    var tdata=new Uint8Array(chk);
    var i;
    for(i=0;i<1024;i++){
      tdata[i]=0x30;
      tdata[i+1024]=0x31;
    }//next i
    
    var page = 
    "<html>\r\n<body>\r\n<textarea id=\"demo\" rows=\"32\" cols=\"64\"></textarea>\r\n<script>\r\nv­ar ws;\r\nvar data=\"\";\r\n//setTimeout(function(){\r­\nws = new WebSocket(\"ws://\" + location.host + \"/my_websocket\", \"protocolOne\");\r\nws.onmessage = function (event) { \r\ndata+=event.data;\r\ndocument.getEle­mentById(\"demo\").innerHTML = data.length;\r\nws.send(\"Hello to Espruino!\"); \r\n };\r\n//setTimeout(function() { ws.send(\"Hello to Espruino!\"); }, //1000);}\r\n//,1000);\r\n\r\n</script><­/body>\r\n</html>\r\n"
    ;
    function onPageRequest(req, res) {
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.end(page);
    }
    
    function test(){
    
    console.log("Start connection process");
    var wifi = require("Wifi");
     console.log("Try Connecting to WiFi ",SSID);
     wifi.connect(SSID,{password:key}, function(err) {
      console.log(err);
       if (err){Startagain=1;return;
    }
     console.log("connected? err=", err, "info=", wifi.getIP());
         console.log("Wi-Fi Connected");
         clearInterval( myinterval);
         var t=getTime();
    var server = require('ws').createServer(onPageRequest­);
    server.listen(8080);
    server.on("websocket", function(ws) {
        ws.on('message',function(msg) {
        n--;
      print("n=",n,"t:",(getTime()-t).toFixed(­3),"sec");
          print("[WS] "+JSON.stringify(msg));
          if(n){
            ws.send(E.toString(tdata));
            process.memory();
          }
        });
      t=getTime();
      ws.send(E.toString(tdata));
      process.memory();
      print("n=",n,"t:",(getTime()-t).toFixed(­3),"sec");
    });
     });//end connect
    }//end test
    
    myinterval=setInterval(function () {
      console.log("Test for error");
      if(Startagain){
       Startagain=0;
       test();
      }//end of Startagain
    }, 2000);
    
    test();
    
    
  • The issue you're hitting here is actually one of fragmentation. The standard Flat String allocator tries to allocate a flat string quickly - and if the free list (not the actual data!) gets fragmented it can fail.

    I've now changed E.toString to try harder (which fixes your problem) but have also made is pass through Uint8Arrays if they're backed by a flat string - so in that case it'll make things much faster for you as well.

  • Thanks!

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

Problem with E.toString

Posted by Avatar for ClearMemory041063 @ClearMemory041063

Actions