SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc. svghmi
authorEdouard Tisserant
Fri, 27 Nov 2020 18:06:34 +0100
branchsvghmi
changeset 3080 e5fa1f49f0b9
parent 3079 1021c6c74dde
child 3081 9e55061c87fa
SVGHMI: WIP trying to reduce memory usage : use .onclick onstead of SetAttribute, avoid useless closure and object creation when possible, etc.
svghmi/gen_index_xhtml.xslt
svghmi/svghmi.js
svghmi/widget_jsontable.ysl2
--- a/svghmi/gen_index_xhtml.xslt	Wed Nov 25 14:47:47 2020 +0100
+++ b/svghmi/gen_index_xhtml.xslt	Fri Nov 27 18:06:34 2020 +0100
@@ -3830,6 +3830,28 @@
 </xsl:text>
     <xsl:text>    cache = [0,100,50];
 </xsl:text>
+    <xsl:text>    init() {
+</xsl:text>
+    <xsl:text>        this.spread_json_data_bound = this.spread_json_data.bind(this);
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>
+</xsl:text>
+    <xsl:text>    handle_http_response(response) {
+</xsl:text>
+    <xsl:text>        if (!response.ok) {
+</xsl:text>
+    <xsl:text>          console.log("HTTP error, status = " + response.status);
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>        return response.json();
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>
+</xsl:text>
     <xsl:text>    do_http_request(...opt) {
 </xsl:text>
     <xsl:text>        const query = {
@@ -3864,9 +3886,9 @@
 </xsl:text>
     <xsl:text>        fetch(this.args[0], options)
 </xsl:text>
-    <xsl:text>            .then(res =&gt; res.json())
-</xsl:text>
-    <xsl:text>            .then(this.spread_json_data.bind(this));
+    <xsl:text>            .then(this.handle_http_response)
+</xsl:text>
+    <xsl:text>            .then(this.spread_json_data_bound);
 </xsl:text>
     <xsl:text>
 </xsl:text>
@@ -3880,11 +3902,21 @@
 </xsl:text>
     <xsl:text>    }
 </xsl:text>
-    <xsl:text>    on_click(evt, ...options) {
-</xsl:text>
-    <xsl:text>        this.do_http_request(...options);
-</xsl:text>
-    <xsl:text>    }
+    <xsl:text>    make_on_click(...options){
+</xsl:text>
+    <xsl:text>        return function(evt){
+</xsl:text>
+    <xsl:text>            this.do_http_request(...options);
+</xsl:text>
+    <xsl:text>        }
+</xsl:text>
+    <xsl:text>    }
+</xsl:text>
+    <xsl:text>    // on_click(evt, ...options) {
+</xsl:text>
+    <xsl:text>    //     this.do_http_request(...options);
+</xsl:text>
+    <xsl:text>    // }
 </xsl:text>
     <xsl:text>}
 </xsl:text>
@@ -4073,11 +4105,11 @@
     <xsl:for-each select="$new_expressions/expression[position() &gt; 1][starts-with(@name,'onClick')]">
       <xsl:text>        id("</xsl:text>
       <xsl:value-of select="$elt/@id"/>
-      <xsl:text>").setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt, '</xsl:text>
+      <xsl:text>").onclick = this.make_on_click('</xsl:text>
       <xsl:value-of select="@name"/>
       <xsl:text>', '"+</xsl:text>
       <xsl:value-of select="@content"/>
-      <xsl:text>+"')");
+      <xsl:text>+"');
 </xsl:text>
     </xsl:for-each>
     <xsl:apply-templates mode="json_table_elt_render" select=".">
@@ -4134,9 +4166,9 @@
     </xsl:variable>
     <xsl:text>          id("</xsl:text>
     <xsl:value-of select="@id"/>
-    <xsl:text>").setAttribute("style", "</xsl:text>
+    <xsl:text>").style = "</xsl:text>
     <xsl:value-of select="@style"/>
-    <xsl:text>");
+    <xsl:text>";
 </xsl:text>
     <xsl:apply-templates mode="json_table_render_except_comments" select="*">
       <xsl:with-param name="expressions" select="func:json_expressions(exsl:node-set($new_expressions), $label)"/>
@@ -4146,7 +4178,7 @@
 </xsl:text>
     <xsl:text>          id("</xsl:text>
     <xsl:value-of select="$gid"/>
-    <xsl:text>").setAttribute("style", "display:none");
+    <xsl:text>").style = "display:none";
 </xsl:text>
     <xsl:text>        }
 </xsl:text>
@@ -5985,7 +6017,7 @@
 </xsl:text>
           <xsl:text>var updates = {};
 </xsl:text>
-          <xsl:text>var need_cache_apply = []; 
+          <xsl:text>var need_cache_apply = [];
 </xsl:text>
           <xsl:text>
 </xsl:text>
@@ -6065,7 +6097,7 @@
 </xsl:text>
           <xsl:text>    STRING: (dv, offset) =&gt; {
 </xsl:text>
-          <xsl:text>        size = dv.getInt8(offset);
+          <xsl:text>        const size = dv.getInt8(offset);
 </xsl:text>
           <xsl:text>        return [
 </xsl:text>
@@ -6247,13 +6279,15 @@
 </xsl:text>
           <xsl:text>
 </xsl:text>
+          <xsl:text>hmi_hash_u8 = new Uint8Array(hmi_hash);
+</xsl:text>
           <xsl:text>
 </xsl:text>
           <xsl:text>function send_blob(data) {
 </xsl:text>
           <xsl:text>    if(data.length &gt; 0) {
 </xsl:text>
-          <xsl:text>        ws.send(new Blob([new Uint8Array(hmi_hash)].concat(data)));
+          <xsl:text>        ws.send(new Blob([hmi_hash_u8].concat(data)));
 </xsl:text>
           <xsl:text>    };
 </xsl:text>
@@ -6279,7 +6313,7 @@
 </xsl:text>
           <xsl:text>        binary[0] = str.length;
 </xsl:text>
-          <xsl:text>        for(var i = 0; i &lt; str.length; i++){
+          <xsl:text>        for(let i = 0; i &lt; str.length; i++){
 </xsl:text>
           <xsl:text>            binary[i+1] = str.charCodeAt(i);
 </xsl:text>
@@ -6667,11 +6701,11 @@
 </xsl:text>
           <xsl:text>    }
 </xsl:text>
-          <xsl:text>    var new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
-</xsl:text>
-          <xsl:text>
-</xsl:text>
-          <xsl:text>    container_id = page_name + (page_index != undefined ? page_index : "");
+          <xsl:text>    const new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
+</xsl:text>
+          <xsl:text>
+</xsl:text>
+          <xsl:text>    const container_id = page_name + (page_index != undefined ? page_index : "");
 </xsl:text>
           <xsl:text>
 </xsl:text>
@@ -6805,7 +6839,7 @@
 </xsl:text>
           <xsl:text>
 </xsl:text>
-          <xsl:text>var xmlns = "http://www.w3.org/2000/svg";
+          <xsl:text>const xmlns = "http://www.w3.org/2000/svg";
 </xsl:text>
           <xsl:text>var edit_callback;
 </xsl:text>
@@ -6831,10 +6865,6 @@
 </xsl:text>
           <xsl:text>
 </xsl:text>
-          <xsl:text>
-</xsl:text>
-          <xsl:text>
-</xsl:text>
           <xsl:text>var current_modal; /* TODO stack ?*/
 </xsl:text>
           <xsl:text>
--- a/svghmi/svghmi.js	Wed Nov 25 14:47:47 2020 +0100
+++ b/svghmi/svghmi.js	Fri Nov 27 18:06:34 2020 +0100
@@ -1,7 +1,7 @@
 // svghmi.js
 
 var updates = {};
-var need_cache_apply = []; 
+var need_cache_apply = [];
 
 
 function dispatch_value(index, value) {
@@ -41,7 +41,7 @@
     NODE: (dv,offset) => [dv.getInt8(offset, true), 1],
     REAL: (dv,offset) => [dv.getFloat32(offset, true), 4],
     STRING: (dv, offset) => {
-        size = dv.getInt8(offset);
+        const size = dv.getInt8(offset);
         return [
             String.fromCharCode.apply(null, new Uint8Array(
                 dv.buffer, /* original buffer */
@@ -132,10 +132,11 @@
     }
 };
 
+hmi_hash_u8 = new Uint8Array(hmi_hash);
 
 function send_blob(data) {
     if(data.length > 0) {
-        ws.send(new Blob([new Uint8Array(hmi_hash)].concat(data)));
+        ws.send(new Blob([hmi_hash_u8].concat(data)));
     };
 };
 
@@ -148,7 +149,7 @@
         str = str.slice(0,128);
         binary = new Uint8Array(str.length + 1);
         binary[0] = str.length;
-        for(var i = 0; i < str.length; i++){
+        for(let i = 0; i < str.length; i++){
             binary[i+1] = str.charCodeAt(i);
         }
         return binary;
@@ -342,9 +343,9 @@
     if(old_desc){
         old_desc.widgets.map(([widget,relativeness])=>widget.unsub());
     }
-    var new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
-
-    container_id = page_name + (page_index != undefined ? page_index : "");
+    const new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
+
+    const container_id = page_name + (page_index != undefined ? page_index : "");
 
     new_desc.widgets.map(([widget,relativeness])=>widget.sub(new_offset,relativeness,container_id));
 
@@ -411,7 +412,7 @@
 
 };
 
-var xmlns = "http://www.w3.org/2000/svg";
+const xmlns = "http://www.w3.org/2000/svg";
 var edit_callback;
 const localtypes = {"PAGE_LOCAL":null, "HMI_LOCAL":null}
 function edit_value(path, valuetype, callback, initial, size) {
--- a/svghmi/widget_jsontable.ysl2	Wed Nov 25 14:47:47 2020 +0100
+++ b/svghmi/widget_jsontable.ysl2	Fri Nov 27 18:06:34 2020 +0100
@@ -5,6 +5,17 @@
     class JsonTableWidget extends Widget{
         // arbitrary defaults to avoid missing entries in query
         cache = [0,100,50];
+        init() {
+            this.spread_json_data_bound = this.spread_json_data.bind(this);
+        }
+
+        handle_http_response(response) {
+            if (!response.ok) {
+              console.log("HTTP error, status = " + response.status);
+            }
+            return response.json();
+        }
+
         do_http_request(...opt) {
             const query = {
                 args: this.args,
@@ -22,17 +33,22 @@
             };
 
             fetch(this.args[0], options)
-                .then(res => res.json())
-                .then(this.spread_json_data.bind(this));
+                .then(this.handle_http_response)
+                .then(this.spread_json_data_bound);
 
         }
         dispatch(value, oldval, index) {
             this.cache[index] = value;
             this.do_http_request();
         }
-        on_click(evt, ...options) {
-            this.do_http_request(...options);
-        }
+        make_on_click(...options){
+            return function(evt){
+                this.do_http_request(...options);
+            }
+        }
+        // on_click(evt, ...options) {
+        //     this.do_http_request(...options);
+        // }
     }
     ||
 
@@ -169,7 +185,8 @@
 
     const "elt",".";
     foreach "$new_expressions/expression[position() > 1][starts-with(@name,'onClick')]"
-    |         id("«$elt/@id»").setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt, '«@name»', '"+«@content»+"')");
+    //|         id("«$elt/@id»").setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt, '«@name»', '"+«@content»+"')");
+    |         id("«$elt/@id»").onclick = this.make_on_click('«@name»', '"+«@content»+"');
 
     apply ".", mode="json_table_elt_render"
         with "expressions", "$new_expressions";
@@ -200,14 +217,16 @@
     }
 
     // revert hiding in case it did happen before
-    |           id("«@id»").setAttribute("style", "«@style»");
+    // |           id("«@id»").setAttribute("style", "«@style»");
+    |           id("«@id»").style = "«@style»";
 
     apply "*", mode="json_table_render_except_comments" {
         with "expressions", "func:json_expressions(exsl:node-set($new_expressions), $label)";
         with "widget_elts", "$widget_elts";
     }
     |         } catch(err) {
-    |           id("«$gid»").setAttribute("style", "display:none");
+    // |           id("«$gid»").setAttribute("style", "display:none");
+    |           id("«$gid»").style = "display:none";
     |         }
 }