• Esprusino on ESP32, I write some codes to transfer data from serial port to a websocket server(nodejs). I use 'ws' module to transfer the data. The Serial2 is set to baudrate 115200, In ten seconds, about 23KB data will be received by Serial2 port. The Serial2.on('data', ...) returns about 230 bytes datas each time. In Serial2.on('data', ...) , I want to transfer the received data (about 230 bytes) to the server by ws.send(), but this will halt the program(the program no responsing). If I cache the 230 bytes to a string or a array until all the 23KB data are received, then send the data by ws.send(), it will take about 120 seconds to trasnsfer them to the server.
    I try the work with 'net' module, I can transfer 230bytes data in Serial2.on('data', ...) directly, without cacheing.
    Then I try the wok with a websocket module written in c++ in arduino-esp32, I can transfer 230bytes data in Serial2.on('data', ...) directly(without cacheing) too.

    How to fast the data transfer rate with 'ws' module in Esrpuino?

  • I have wrote some test codes:

    function onInit(){
      var ssid = "ssid";
      var wifiOpts = {password:"pwd"};
      var wifi = require("Wifi");
    
      wifi.connect(ssid, wifiOpts, function(err){
        console.log("connected? err=", err, "info=", wifi.getIP());
        var WebSocket = require("ws");
        var host = "192.168.1.9";
        var ws = new WebSocket(host,{
          path: '/',
          port: 5004, // default is 80
          protocolVersion: 13, // websocket protocol version, default is 13
          origin: 'Espruino',
          keepAlive: 60,
        });
    
        ws.on('open', function() {
          console.log("connected");
          //ws.send('hello, server');
          var packet = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
          var pktNum = 0;
          var ta = 0;
          var id = setInterval(function(){
            var t1 = getTime();
            ws.send(btoa(packet));
            pktNum ++;
            console.log("Packet NO.: " + pktNum + ", time used: " + (t2 = getTime() - t1) + "s");
            ta += t2;
            if(pktNum >=101){
              console.log("total time used: " + ta +"s");
              clearInterval(id);
            }
          }, 100);
        });
      });
    }
    

    the result:

    connected? err= null info= {
      "ip": "192.168.1.30",
      "netmask": "255.255.255.0",
      "gw": "192.168.1.1",
      "mac": "30:ae:a4:03:96:a8"
     }
    connected
    Packet NO.: 1, time used: 0.85709s
    Packet NO.: 2, time used: 0.838764s
    Packet NO.: 3, time used: 0.856456s
    Packet NO.: 4, time used: 0.837004s
    Packet NO.: 5, time used: 0.845455s
    Packet NO.: 6, time used: 0.847384s
    Packet NO.: 7, time used: 0.84427s
    Packet NO.: 8, time used: 0.850653s
    Packet NO.: 9, time used: 0.840083s
    Packet NO.: 10, time used: 0.841126s
    Packet NO.: 11, time used: 0.849597s
    Packet NO.: 12, time used: 0.846575s
    Packet NO.: 13, time used: 0.851111s
    Packet NO.: 14, time used: 0.845253s
    Packet NO.: 15, time used: 0.861927s
    Packet NO.: 16, time used: 0.848568s
    Packet NO.: 17, time used: 0.85375s
    Packet NO.: 18, time used: 0.839241s
    Packet NO.: 19, time used: 0.837366s
    Packet NO.: 20, time used: 0.846501s
    Packet NO.: 21, time used: 0.851264s
    Packet NO.: 22, time used: 0.844203s
    Packet NO.: 23, time used: 0.850979s
    Packet NO.: 24, time used: 0.851601s
    Packet NO.: 25, time used: 0.844725s
    Packet NO.: 26, time used: 0.846098s
    Packet NO.: 27, time used: 0.84291s
    Packet NO.: 28, time used: 0.844193s
    Packet NO.: 29, time used: 0.850243s
    Packet NO.: 30, time used: 0.854025s
    Packet NO.: 31, time used: 0.84941s
    Packet NO.: 32, time used: 0.84723s
    Packet NO.: 33, time used: 0.84363s
    Packet NO.: 34, time used: 0.850008s
    Packet NO.: 35, time used: 0.843929s
    Packet NO.: 36, time used: 0.859503s
    Packet NO.: 37, time used: 0.845025s
    Packet NO.: 38, time used: 0.838622s
    Packet NO.: 39, time used: 0.86317899999s
    Packet NO.: 40, time used: 0.847434s
    Packet NO.: 41, time used: 0.841337s
    Packet NO.: 42, time used: 0.84749s
    Packet NO.: 43, time used: 0.845084s
    Packet NO.: 44, time used: 0.859161s
    Packet NO.: 45, time used: 0.854041s
    Packet NO.: 46, time used: 0.853847s
    Packet NO.: 47, time used: 0.84596s
    Packet NO.: 48, time used: 0.855874s
    Packet NO.: 49, time used: 0.846709s
    Packet NO.: 50, time used: 0.850626s
    Packet NO.: 51, time used: 0.855101s
    Packet NO.: 52, time used: 0.843922s
    Packet NO.: 53, time used: 0.855193s
    Packet NO.: 54, time used: 0.850098s
    Packet NO.: 55, time used: 0.85086299999s
    Packet NO.: 56, time used: 0.843604s
    Packet NO.: 57, time used: 0.840063s
    Packet NO.: 58, time used: 0.849205s
    Packet NO.: 59, time used: 0.84311899999s
    Packet NO.: 60, time used: 0.847484s
    Packet NO.: 61, time used: 0.855748s
    Packet NO.: 62, time used: 0.856332s
    Packet NO.: 63, time used: 0.849081s
    Packet NO.: 64, time used: 0.847368s
    Packet NO.: 65, time used: 0.8664s
    Packet NO.: 66, time used: 0.855494s
    Packet NO.: 67, time used: 0.845644s
    Packet NO.: 68, time used: 0.840538s
    Packet NO.: 69, time used: 0.847404s
    Packet NO.: 70, time used: 0.852032s
    Packet NO.: 71, time used: 0.84936300000s
    Packet NO.: 72, time used: 0.847706s
    Packet NO.: 73, time used: 0.851532s
    Packet NO.: 74, time used: 0.842296s
    Packet NO.: 75, time used: 0.84484s
    Packet NO.: 76, time used: 0.847341s
    Packet NO.: 77, time used: 0.851096s
    Packet NO.: 78, time used: 0.85451s
    Packet NO.: 79, time used: 0.853806s
    Packet NO.: 80, time used: 0.857314s
    Packet NO.: 81, time used: 0.842491s
    Packet NO.: 82, time used: 0.84421200000s
    Packet NO.: 83, time used: 0.846194s
    Packet NO.: 84, time used: 0.841761s
    Packet NO.: 85, time used: 0.86257s
    Packet NO.: 86, time used: 0.847736s
    Packet NO.: 87, time used: 0.843611s
    Packet NO.: 88, time used: 0.84158s
    Packet NO.: 89, time used: 0.84169s
    Packet NO.: 90, time used: 0.84392s
    Packet NO.: 91, time used: 0.841432s
    Packet NO.: 92, time used: 0.849577s
    Packet NO.: 93, time used: 0.848673s
    Packet NO.: 94, time used: 0.841546s
    Packet NO.: 95, time used: 0.845739s
    Packet NO.: 96, time used: 0.849719s
    Packet NO.: 97, time used: 0.839512s
    Packet NO.: 98, time used: 0.838894s
    Packet NO.: 99, time used: 0.850167s
    Packet NO.: 100, time used: 0.857364s
    Packet NO.: 101, time used: 0.846186s
    total time used: 85.66558500000s
    

    per 230 bytes packet needs 850ms to be transfered to websocket server(nodejs).

  • The data rate depends on loads of things so I can't give you a sensible value, but it might be slowed down by the need to 'unmask' the received data - which would be very dependent on JS execution speed.

  • I run the test code on ESP32 module with 16M falsh.

    In the test code, I store data just in a String var. And with no btoa(), set time interval to zero in setInterval, I get the same result.

  • test code with no btoa(), and interval = 0

    function onInit(){
      var ssid = "HGiga3";
      var wifiOpts = {password:"20071203"};
      var wifi = require("Wifi");
    
      wifi.connect(ssid, wifiOpts, function(err){
        console.log("connected? err=", err, "info=", wifi.getIP());
        var WebSocket = require("ws");
        var host = "192.168.1.9";
        var ws = new WebSocket(host,{
          path: '/',
          port: 5004, // default is 80
          protocolVersion: 13, // websocket protocol version, default is 13
          origin: 'Espruino',
          keepAlive: 60,
        });
    
        ws.on('open', function() {
          console.log("connected");
          //ws.send('hello, server');
          var packet = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
          var pktNum = 0;
          var ta = 0;
          var id = setInterval(function(){
            var t1 = getTime();
            ws.send(packet);
            pktNum ++;
            console.log("Packet NO.: " + pktNum + ", time used: " + (t2 = getTime() - t1) + "s");
            ta += t2;
            if(pktNum >=101){
              console.log("total time used: " + ta +"s");
              clearInterval(id);
            }
          }, 0);
        });
      });
    }
    

    result:

    connected? err= null info= {
      "ip": "192.168.1.30",
      "netmask": "255.255.255.0",
      "gw": "192.168.1.1",
      "mac": "30:ae:a4:03:96:a8"
     }
    connected
    Packet NO.: 1, time used: 0.635692s
    Packet NO.: 2, time used: 0.643326s
    Packet NO.: 3, time used: 0.639247s
    Packet NO.: 4, time used: 0.637486s
    Packet NO.: 5, time used: 0.638007s
    Packet NO.: 6, time used: 0.639673s
    Packet NO.: 7, time used: 0.635873s
    Packet NO.: 8, time used: 0.639083s
    Packet NO.: 9, time used: 0.638372s
    Packet NO.: 10, time used: 0.635825s
    Packet NO.: 11, time used: 0.63933s
    Packet NO.: 12, time used: 0.640514s
    Packet NO.: 13, time used: 0.651622s
    Packet NO.: 14, time used: 0.635399s
    Packet NO.: 15, time used: 0.633999s
    Packet NO.: 16, time used: 0.642046s
    Packet NO.: 17, time used: 0.636034s
    Packet NO.: 18, time used: 0.634s
    Packet NO.: 19, time used: 0.641917s
    Packet NO.: 20, time used: 0.634763s
    Packet NO.: 21, time used: 0.637004s
    Packet NO.: 22, time used: 0.639767s
    Packet NO.: 23, time used: 0.640957s
    Packet NO.: 24, time used: 0.641996s
    Packet NO.: 25, time used: 0.641126s
    Packet NO.: 26, time used: 0.63957s
    Packet NO.: 27, time used: 0.641609s
    Packet NO.: 28, time used: 0.637018s
    Packet NO.: 29, time used: 0.6368s
    Packet NO.: 30, time used: 0.634749s
    Packet NO.: 31, time used: 0.633586s
    Packet NO.: 32, time used: 0.634311s
    Packet NO.: 33, time used: 0.63496s
    Packet NO.: 34, time used: 0.640297s
    Packet NO.: 35, time used: 0.64408s
    Packet NO.: 36, time used: 0.63855s
    Packet NO.: 37, time used: 0.632856s
    Packet NO.: 38, time used: 0.639827s
    Packet NO.: 39, time used: 0.641707s
    Packet NO.: 40, time used: 0.635856s
    Packet NO.: 41, time used: 0.638333s
    Packet NO.: 42, time used: 0.641669s
    Packet NO.: 43, time used: 0.634372s
    Packet NO.: 44, time used: 0.65415s
    Packet NO.: 45, time used: 0.639517s
    Packet NO.: 46, time used: 0.637973s
    Packet NO.: 47, time used: 0.644115s
    Packet NO.: 48, time used: 0.638485s
    Packet NO.: 49, time used: 0.642308s
    Packet NO.: 50, time used: 0.639105s
    Packet NO.: 51, time used: 0.636765s
    Packet NO.: 52, time used: 0.631903s
    Packet NO.: 53, time used: 0.681386s
    Packet NO.: 54, time used: 0.634737s
    Packet NO.: 55, time used: 0.641648s
    Packet NO.: 56, time used: 0.643582s
    Packet NO.: 57, time used: 0.636885s
    Packet NO.: 58, time used: 0.631757s
    Packet NO.: 59, time used: 0.642512s
    Packet NO.: 60, time used: 0.639893s
    Packet NO.: 61, time used: 0.638397s
    Packet NO.: 62, time used: 0.63751s
    Packet NO.: 63, time used: 0.641528s
    Packet NO.: 64, time used: 0.639858s
    Packet NO.: 65, time used: 0.642329s
    Packet NO.: 66, time used: 0.636603s
    Packet NO.: 67, time used: 0.634986s
    Packet NO.: 68, time used: 0.641883s
    Packet NO.: 69, time used: 0.637135s
    Packet NO.: 70, time used: 0.639046s
    Packet NO.: 71, time used: 0.641357s
    Packet NO.: 72, time used: 0.633942s
    Packet NO.: 73, time used: 0.634675s
    Packet NO.: 74, time used: 0.642398s
    Packet NO.: 75, time used: 0.650468s
    Packet NO.: 76, time used: 0.638624s
    Packet NO.: 77, time used: 0.643335s
    Packet NO.: 78, time used: 0.637059s
    Packet NO.: 79, time used: 0.635053s
    Packet NO.: 80, time used: 0.637182s
    Packet NO.: 81, time used: 0.638033s
    Packet NO.: 82, time used: 0.635974s
    Packet NO.: 83, time used: 0.638443s
    Packet NO.: 84, time used: 0.63591s
    Packet NO.: 85, time used: 0.639598s
    Packet NO.: 86, time used: 0.639959s
    Packet NO.: 87, time used: 0.637911s
    Packet NO.: 88, time used: 0.638151s
    Packet NO.: 89, time used: 0.636811s
    Packet NO.: 90, time used: 0.636061s
    Packet NO.: 91, time used: 0.636077s
    Packet NO.: 92, time used: 0.637843s
    Packet NO.: 93, time used: 0.641588s
    Packet NO.: 94, time used: 0.639297s
    Packet NO.: 95, time used: 0.642088s
    Packet NO.: 96, time used: 0.635662s
    Packet NO.: 97, time used: 0.638305s
    Packet NO.: 98, time used: 0.634205s
    Packet NO.: 99, time used: 0.644576s
    Packet NO.: 100, time used: 0.644314s
    Packet NO.: 101, time used: 0.639154s
    total time used: 64.56325700000s
    

    with no btoa(), about 200ms is saved per 230 bytes packet.

  • I try to transfer 230 bytes packet per 100ms with a C++ websocket lib - arduinoWebSockets on esp8266, it's ok. The data rate is at least 6 times faster then 'ws' on Espruino. Even esp8266 is slower then Esp32 module.

    Is there some method to enchance the performance of 'ws' ?

  • The test codes using 'net' module on Esp32. very fast.

    function onInit(){
    
      var ssid = "HGiga3";
      var wifiOpts = {password:"20071203"};
      var wifi = require("Wifi");
    
      wifi.connect(ssid, wifiOpts, function(err){
        console.log("connected? err=", err, "info=", wifi.getIP());
    
        var client = require("net").connect({host: "192.168.1.9", port: 5004}, function() {
          console.log("connected");
          //ws.send('hello, server');
          var packet = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
          var pktNum = 0;
          var ta = 0;
          var id = setInterval(function(){
            var t1 = getTime();
            client.write(packet);
            pktNum ++;
            console.log("Packet NO.: " + pktNum + ", time used: " + (t2 = getTime() - t1) + "s");
            ta += t2;
            if(pktNum >=101){
              console.log("total time used: " + ta +"s");
              clearInterval(id);
            }
          }, 0);
        });
      });
    
    } // END OF : function onInit(){
    
    

    result:

    connected? err= null info= {
      "ip": "192.168.1.30",
      "netmask": "255.255.255.0",
      "gw": "192.168.1.1",
      "mac": "30:ae:a4:03:96:a8"
     }
    connected
    Packet NO.: 1, time used: 0.004231s
    Packet NO.: 2, time used: 0.006114s
    Packet NO.: 3, time used: 0.004296s
    Packet NO.: 4, time used: 0.004198s
    Packet NO.: 5, time used: 0.004113s
    Packet NO.: 6, time used: 0.005927s
    Packet NO.: 7, time used: 0.004045s
    Packet NO.: 8, time used: 0.004094s
    Packet NO.: 9, time used: 0.006462s
    Packet NO.: 10, time used: 0.004759s
    Packet NO.: 11, time used: 0.004114s
    Packet NO.: 12, time used: 0.007091s
    Packet NO.: 13, time used: 0.006509s
    Packet NO.: 14, time used: 0.004279s
    Packet NO.: 15, time used: 0.005615s
    Packet NO.: 16, time used: 0.004196s
    Packet NO.: 17, time used: 0.003922s
    Packet NO.: 18, time used: 0.004579s
    Packet NO.: 19, time used: 0.003968s
    Packet NO.: 20, time used: 0.003939s
    Packet NO.: 21, time used: 0.004289s
    Packet NO.: 22, time used: 0.004283s
    Packet NO.: 23, time used: 0.003999s
    Packet NO.: 24, time used: 0.003984s
    Packet NO.: 25, time used: 0.004023s
    Packet NO.: 26, time used: 0.004017s
    Packet NO.: 27, time used: 0.004048s
    Packet NO.: 28, time used: 0.004591s
    Packet NO.: 29, time used: 0.004092s
    Packet NO.: 30, time used: 0.004068s
    Packet NO.: 31, time used: 0.00434s
    Packet NO.: 32, time used: 0.004269s
    Packet NO.: 33, time used: 0.004151s
    Packet NO.: 34, time used: 0.004142s
    Packet NO.: 35, time used: 0.004177s
    Packet NO.: 36, time used: 0.004166s
    Packet NO.: 37, time used: 0.004199s
    Packet NO.: 38, time used: 0.004697s
    Packet NO.: 39, time used: 0.00427s
    Packet NO.: 40, time used: 0.004582s
    Packet NO.: 41, time used: 0.00449s
    Packet NO.: 42, time used: 0.004288s
    Packet NO.: 43, time used: 0.004275s
    Packet NO.: 44, time used: 0.004271s
    Packet NO.: 45, time used: 0.004327s
    Packet NO.: 46, time used: 0.004298s
    Packet NO.: 47, time used: 0.004333s
    Packet NO.: 48, time used: 0.005087s
    Packet NO.: 49, time used: 0.004388s
    Packet NO.: 50, time used: 0.004353s
    Packet NO.: 51, time used: 0.004907s
    Packet NO.: 52, time used: 0.004524s
    Packet NO.: 53, time used: 0.00496s
    Packet NO.: 54, time used: 0.00446s
    Packet NO.: 55, time used: 0.00546s
    Packet NO.: 56, time used: 0.005477s
    Packet NO.: 57, time used: 0.00445s
    Packet NO.: 58, time used: 0.004393s
    Packet NO.: 59, time used: 0.004385s
    Packet NO.: 60, time used: 0.004417s
    Packet NO.: 61, time used: 0.004403s
    Packet NO.: 62, time used: 0.004368s
    Packet NO.: 63, time used: 0.004339s
    Packet NO.: 64, time used: 0.00434s
    Packet NO.: 65, time used: 0.004344s
    Packet NO.: 66, time used: 0.0043s
    Packet NO.: 67, time used: 0.004294s
    Packet NO.: 68, time used: 0.004246s
    Packet NO.: 69, time used: 0.00437s
    Packet NO.: 70, time used: 0.004324s
    Packet NO.: 71, time used: 0.005413s
    Packet NO.: 72, time used: 0.004527s
    Packet NO.: 73, time used: 0.004495s
    Packet NO.: 74, time used: 0.004142s
    Packet NO.: 75, time used: 0.004123s
    Packet NO.: 76, time used: 0.004212s
    Packet NO.: 77, time used: 0.0057s
    Packet NO.: 78, time used: 0.00406s
    Packet NO.: 79, time used: 0.004445s
    Packet NO.: 80, time used: 0.004121s
    Packet NO.: 81, time used: 0.004131s
    Packet NO.: 82, time used: 0.004038s
    Packet NO.: 83, time used: 0.003966s
    Packet NO.: 84, time used: 0.004073s
    Packet NO.: 85, time used: 0.006238s
    Packet NO.: 86, time used: 0.004172s
    Packet NO.: 87, time used: 0.005971s
    Packet NO.: 88, time used: 0.005622s
    Packet NO.: 89, time used: 0.006437s
    Packet NO.: 90, time used: 0.004657s
    Packet NO.: 91, time used: 0.006027s
    Packet NO.: 92, time used: 0.004347s
    Packet NO.: 93, time used: 0.004164s
    Packet NO.: 94, time used: 0.003917s
    Packet NO.: 95, time used: 0.006005s
    Packet NO.: 96, time used: 0.006223s
    Packet NO.: 97, time used: 0.004181s
    Packet NO.: 98, time used: 0.006128s
    Packet NO.: 99, time used: 0.004149s
    Packet NO.: 100, time used: 0.006002s
    Packet NO.: 101, time used: 0.004063s
    total time used: 0.465458s
    
  • Is there some method to enchance the performance of 'ws' ?

    Chances are it's this code that is slowing things down:

    https://github.com/espruino/EspruinoDocs/blob/master/modules/ws.js#L230

    You could probably do something like this to make Espruino head through it 32 bits at a time instead of 8:

    masked = new Uint32Array(1+((msg.length+3)>>2));
    var m8 = new Uint8Array(masked.buffer,0,4+msg.length);
    m8.set(mask,0);
    m8.set(msg,4);
    var m = masked[0];
    for (var i=masked.length-1;i>0;i--)masked[i]^=m;
    // E.mapInPlace could be even faster here
    this.socket.write(m8);
    

    But you'd have to have a play around yourself - I haven't tested that.

  • Just to add - if your server supports it then you may be able to turn masking off, which would help things a huge amount.

  • @Gordon
    Your code enhance the performance of 'ws' aobut five times.

    in the 'ws' codes:

        var mask = [];
        for (var ix = 0; ix < 4; ix++){
          var rnd = Math.floor( Math.random() * 255 );
          mask[ix] = rnd;
          //masked += strChr(rnd);
        }
        var masked = new Uint32Array(1+((msg.length+3)>>2));
        var m8 = new Uint8Array(masked.buffer, 0, (4 + msg.length));
        m8.set(mask,0);
        m8.set(msg,4);
        var m = masked[0];
        for (var i=1;i<masked.length;i++) {
          masked[i]^=m;
        }
        // E.mapInPlace could be even faster here
        this.socket.write(m8);
    

    result:

    connected? err= null info= {
      "ip": "192.168.1.30",
      "netmask": "255.255.255.0",
      "gw": "192.168.1.1",
      "mac": "30:ae:a4:03:96:a8"
     }
    connected
    Packet NO.: 1, time used: 0.122781s
    Packet NO.: 2, time used: 0.130532s
    Packet NO.: 3, time used: 0.130694s
    Packet NO.: 4, time used: 0.121443s
    Packet NO.: 5, time used: 0.122264s
    Packet NO.: 6, time used: 0.128198s
    Packet NO.: 7, time used: 0.118977s
    Packet NO.: 8, time used: 0.128156s
    Packet NO.: 9, time used: 0.126372s
    Packet NO.: 10, time used: 0.128605s
    Packet NO.: 11, time used: 0.123227s
    Packet NO.: 12, time used: 0.129712s
    Packet NO.: 13, time used: 0.122637s
    Packet NO.: 14, time used: 0.128667s
    Packet NO.: 15, time used: 0.123411s
    Packet NO.: 16, time used: 0.122551s
    Packet NO.: 17, time used: 0.130601s
    Packet NO.: 18, time used: 0.124756s
    Packet NO.: 19, time used: 0.130782s
    Packet NO.: 20, time used: 0.125312s
    Packet NO.: 21, time used: 0.125905s
    Packet NO.: 22, time used: 0.142719s
    Packet NO.: 23, time used: 0.127608s
    Packet NO.: 24, time used: 0.126586s
    Packet NO.: 25, time used: 0.127527s
    Packet NO.: 26, time used: 0.131625s
    Packet NO.: 27, time used: 0.134015s
    Packet NO.: 28, time used: 0.13283s
    Packet NO.: 29, time used: 0.132503s
    Packet NO.: 30, time used: 0.125586s
    Packet NO.: 31, time used: 0.134384s
    Packet NO.: 32, time used: 0.133459s
    Packet NO.: 33, time used: 0.128191s
    Packet NO.: 34, time used: 0.12743s
    Packet NO.: 35, time used: 0.133592s
    Packet NO.: 36, time used: 0.134646s
    Packet NO.: 37, time used: 0.132336s
    Packet NO.: 38, time used: 0.128793s
    Packet NO.: 39, time used: 0.137423s
    Packet NO.: 40, time used: 0.128829s
    Packet NO.: 41, time used: 0.127535s
    Packet NO.: 42, time used: 0.135589s
    Packet NO.: 43, time used: 0.129962s
    Packet NO.: 44, time used: 0.135888s
    Packet NO.: 45, time used: 0.127731s
    Packet NO.: 46, time used: 0.13064s
    Packet NO.: 47, time used: 0.135926s
    Packet NO.: 48, time used: 0.135231s
    Packet NO.: 49, time used: 0.135276s
    Packet NO.: 50, time used: 0.137039s
    Packet NO.: 51, time used: 0.136779s
    Packet NO.: 52, time used: 0.132308s
    Packet NO.: 53, time used: 0.130578s
    Packet NO.: 54, time used: 0.130833s
    Packet NO.: 55, time used: 0.145101s
    Packet NO.: 56, time used: 0.134404s
    Packet NO.: 57, time used: 0.138408s
    Packet NO.: 58, time used: 0.132389s
    Packet NO.: 59, time used: 0.146416s
    Packet NO.: 60, time used: 0.136446s
    ERROR: Out of Memory!
    ERROR: Ctrl-C while processing interval - removing it.
    Execution Interrupted during event processing.
    at line 1 col 461
    ...[f]^=i;this.socket.write(c),e=undefined,b=undefined,c=undefi...
                                  ^
    in function "send" called from line 2 col 23
            ws.send(packet);
                          ^
    in function called from system
    

    What strange is that after 60 packets are transfered, the program throws " out of memory " error, every time.

    AND , when the server receives the second packet, it crashed every time.

    Server is listening on port 5004
    a client connected
    isTalking : false
    <Buffer 81 fe>
    received data: 1,230
    <Buffer 35 38>
    events.js:160
          throw er; // Unhandled 'error' event
          ^
    
    Error: invalid opcode: 5
    
    

    The first two bytes of the first packet is correct, and that of the second packet is wrong. The first tow bytes of the second(and every frame/packet) should be , but they are now.

    The error is throwed by the codes in Receiver.js of ws module on nodejs

    if ((buf[0] & 0x30) !== 0x00) {
          this.error(new Error('RSV2 and RSV3 must be clear'), 1002);
          return;
        }
    

    I'll try to find the problem.

  • The out of memory could be that you're now sending data faster than the ESP8266 can send it down WiFi! The 'send' function will return control to your code before the data packets have actually left the ESP8266.

    I'd compare the data you get from the 2 bits of code - maybe there is something wrong with my code.

    It could also be that the wrong amount of data is getting sent somehow? That might explain the 'invalid opcode'

  • I write some test codes.

    var strChr = String.fromCharCode;
    
    var msg = "1234567890";
    
    for(var lp=0; lp<8;lp++){
      // mask
      var mask = [];
      var masked1 = '';
      for (var ix = 0; ix < 4; ix++){
        var rnd = Math.floor( Math.random() * 255 );
        mask[ix] = rnd;
        masked1 += strChr(rnd);
      }
    
      // masked1:
      for (var ix = 0; ix < msg.length; ix++){
        masked1 += strChr(msg.charCodeAt(ix) ^ mask[ix & 3]);
      }
      // masked1 char code
      var masked1code = [];
      for(var i = 0;i<masked1.length; i++){
        masked1code[i] = masked1.charCodeAt(i);
      }
    
    
      // masked2
      var masked2 = new Uint32Array(1+((msg.length+3)>>2));
      var m8 = new Uint8Array(masked2.buffer, 0, (4 + msg.length));
      m8.set(mask,0);
      m8.set(msg,4);
      var m = masked2[0];
      for (var i=1;i<masked2.length;i++) {
        masked2[i]^=m;
      }
      console.log("----------------------lp(" + lp + ")--------------------");
      console.log(mask);
      console.log(masked1code);
      console.log(masked2);
      console.log(m8);
    }
    
    

    result:

    >----------------------lp(0)--------------------
    [ 244, 247, 131, 224 ]
    [ 244, 247, 131, 224, 197, 197, 176, 212, 193, 193, 180, 216, 205, 199 ]
    new Uint32Array([3766745076, 3568354757, 3635724737, 3766732749])
    new Uint8Array([244, 247, 131, 224, 197, 197, 176, 212, 193, 193, 180, 216, 205, 199])
    ----------------------lp(1)--------------------
    [ 203, 75, 141, 225 ]
    [ 203, 75, 141, 225, 250, 121, 190, 213, 254, 125, 186, 217, 242, 123 ]
    new Uint32Array([3784133579, 3586030074, 3652877822, 3784145906])
    new Uint8Array([203, 75, 141, 225, 250, 121, 190, 213, 254, 125, 186, 217, 242, 123])
    ----------------------lp(2)--------------------
    [ 172, 35, 218, 166 ]
    [ 172, 35, 218, 166, 157, 17, 233, 146, 153, 21, 237, 158, 149, 19 ]
    new Uint32Array([2799313836, 2464747933, 2666337689, 2799309717])
    new Uint8Array([172, 35, 218, 166, 157, 17, 233, 146, 153, 21, 237, 158, 149, 19])
    ----------------------lp(3)--------------------
    [ 231, 205, 151, 99 ]
    [ 231, 205, 151, 99, 214, 255, 164, 87, 210, 251, 160, 91, 222, 253 ]
    new Uint32Array([1670893031, 1470431190, 1537276882, 1670905310])
    new Uint8Array([231, 205, 151, 99, 214, 255, 164, 87, 210, 251, 160, 91, 222, 253])
    ----------------------lp(4)--------------------
    [ 121, 220, 55, 245 ]
    [ 121, 220, 55, 245, 72, 238, 4, 193, 76, 234, 0, 205, 64, 236 ]
    new Uint32Array([4114078841, 3238325832, 3439389260, 4114082880])
    new Uint8Array([121, 220, 55, 245, 72, 238, 4, 193, 76, 234, 0, 205, 64, 236])
    ----------------------lp(5)--------------------
    [ 165, 47, 134, 99 ]
    [ 165, 47, 134, 99, 148, 29, 181, 87, 144, 25, 177, 91, 156, 31 ]
    new Uint32Array([1669738405, 1471487380, 1538333072, 1669734300])
    new Uint8Array([165, 47, 134, 99, 148, 29, 181, 87, 144, 25, 177, 91, 156, 31])
    ----------------------lp(6)--------------------
    [ 9, 142, 128, 143 ]
    [ 9, 142, 128, 143, 56, 188, 179, 187, 60, 184, 183, 183, 48, 190 ]
    new Uint32Array([2407566857, 3149118520, 3082270780, 2407579184])
    new Uint8Array([9, 142, 128, 143, 56, 188, 179, 187, 60, 184, 183, 183, 48, 190])
    ----------------------lp(7)--------------------
    [ 217, 225, 170, 12 ]
    [ 217, 225, 170, 12, 232, 211, 153, 56, 236, 215, 157, 52, 224, 209 ]
    new Uint32Array([212525529, 949605352, 882759660, 212521440])
    new Uint8Array([217, 225, 170, 12, 232, 211, 153, 56, 236, 215, 157, 52, 224, 209])
    =undefined
    

    It seems that your codes works well.

  • @Gordon
    I run the codes on ESP32 module.

    As in the 'net' codes, the ESP32 module can transfer 230bytres in 4~6ms with WiFi.

    connected? err= null info= {
      "ip": "192.168.1.30",
      "netmask": "255.255.255.0",
      "gw": "192.168.1.1",
      "mac": "30:ae:a4:03:96:a8"
     }
    connected
    Packet NO.: 1, time used: 0.004231s
    Packet NO.: 2, time used: 0.006114s
    Packet NO.: 3, time used: 0.004296s
    Packet NO.: 4, time used: 0.004198s
    Packet NO.: 5, time used: 0.004113s
    Packet NO.: 6, time used: 0.005927s
    
  • @Gordon
    I change the code

    this.socket.write(m8);
    

    to

    this.socket.write(str(m8)); //  or this.socket.write(String.fromCharCode(m8));
    

    Then , the server will never crashed, and the ESP32 with no out of memroy all the time.

    the m8 stores the char code, so we need to convert them to char by fromCharCode();

    But, the 'ws' is slowed down, per 230 bytes packet needs 600ms to be transfered , and all the 23KB datas need 66 seconds.

  • Ok, thanks - and it's still sending the correct data? That line might be sending the correct length, but I'm not sure if the data will be correct.

    this.socket.write(E.toString(m8).s­ubstr(0,(4 + msg.length))); might be better, but it may hurt performance a bit.

  • Yes, it's sending the correct data by your code

    this.socket.write(E.toString(m8));
    

    or the code below:

    this.socket.write(str(m8)); //  or this.socket.write(String.fromCharCode(m8­));
    

    They have the same performance.

    The m8 stores the char code, so we need to convert them to char by fromCharCode();

    But, the 'ws' is slowed down, per 230 bytes packet needs 600ms to be transfered , and all the 23KB datas need 66 seconds. Before we use UintArray, the total time is 85 seconds.

    Do you think we can find some way to enhance the 'ws' performance to transfer 23KB datas within 10 seconds?

  • Hi, @Gordon

    You are right!

    Follow your suggestion, I write the "C" native Mask library for websocket module on Espruino.
    On Esp32 module, I test the library for some times.
    Without Mask-lib, It takes about 64 seconds to transfer 23KB data to a websocket server.
    By using Mask-lib, It takes about 1.68 second to do the same work.
    Mask-lib can improve the performance of 'ws' about 40 times.

    All codes are here:

    jswrap_mask.h

    [#include](https://forum.espruino.com/search/?q=%23include) "jsvar.h"
    
    JsVar *jswrap_mask_4(JsVar *str);
    

    jswrap_mask.c

    [#include](https://forum.espruino.com/search/?q=%23include) "jswrap_mask.h"
    [#include](https://forum.espruino.com/search/?q=%23include) "jsinteractive.h"
    [#include](https://forum.espruino.com/search/?q=%23include) "jsvar.h"
    [#include](https://forum.espruino.com/search/?q=%23include) "jshardware.h"
    
    // Define the JavaScript class
    /*JSON{
      "type" : "class",
      "class" : "M"
    }*/
    
    // Define the `jswrap_mask_4` to be a `staticmethod` on the `M` class
    /*JSON{
      "type" : "staticmethod",
      "class" : "M",
      "name" : "mask4",
      "generate" : "jswrap_mask_4",
      "params" : [
        ["str","JsVar","An object containing a string"]
      ],
      "return" : ["JsVar","Returns a masked string object"]
    }
    Create a masked string, mask is 4 random chars.
    */
    JsVar *jswrap_mask_4(JsVar *str) {
      if (!jsvIsString(str)) {
        return jsvNewFromEmptyString();
      }
      size_t msglength = jsvGetStringLength(str);
      char *masked = (char *)jsvMalloc(msglength+1);
      jsvGetString(str, masked, msglength+1);
      //jsvUnLock(str); // crash?
      char mask[4] = {0,0,0,0};
    	//String masked = message; //jsvgetstring
    	for (int i = 0; i < 4; i++)
    	{
        char a = (char)jshGetRandomNumber();
        mask[i] = a;
    	}
    	for (int i = 0; i < msglength; i++){
        masked[i] ^= mask[i % 4];
      }
      JsVar *maskedVar = jsvNewFromEmptyString();
      jsvAppendStringBuf(maskedVar, mask, 4);
      jsvAppendStringBuf(maskedVar, masked, msglength);
      jsvFree(masked);
      return maskedVar;
    }
    

    Change in ws.js

    /** Send message based on opcode type */
    WebSocket.prototype.send = function (msg, opcode) {
      opcode = opcode === undefined ? 0x81 : opcode;
      var size = msg.length;
      if (msg.length>125) {
        size = 126;
      }
      this.socket.write(strChr(opcode, size + ( this.masking ? 128 : 0 )));
    
      if (size == 126) {
        // Need to write extra bytes for longer messages
        this.socket.write(strChr(msg.length >> 8));
        this.socket.write(strChr(msg.length));
      }
    
      if (this.masking) { // change is here
        this.socket.write(M.mask4(msg)); // using built-in lib instead of JS masking codes 
      } else {
        this.socket.write(msg);
      }
    };
    

    Espruino is flexible, Cool!

  • That's great - thanks for posting it up!

    If you were using Espruino on a Pico/Wifi/etc then you could actually use the compiled code flag to compile that section of JS to native code :)

    I think eventually I will implement the ws lib natively inside Espruino (to hopefully allow the web IDE to communicate with Wifi-enabled boards), but I'm afraid right now I have a bit too much on my plate!

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

How to fast the data transfer rate with WebSocket module 'ws' in Espruino?

Posted by Avatar for Aifer @Aifer

Actions