Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Memory issue

ANSWERED

I have reached the memory limit in my watchface and am investigating the causes.

I noticed that the call document.getElementById, without other invocation on the returned svg element, produce memory load that will not be recovered by garbage collector.

 

After call getElementById for 72 svg empty elements 11% of memory is allocated and never released

If you uncomment  the line ...getElementById("arc") memory usage increase again 11% so in total will consume 22% memory that will never been released.

 

Output in console:

[14:42:01] App: Hello world! 
[14:42:01] App: MEM:9.5% start 12584/131064 12360-12376
[14:42:01] App: MEM USAGE index.ENTER...................9.7% 9.7% 12768 / 131064
[14:42:01] App: MEM USAGE index.EXIT....................1.2% 10.9% 14296 / 131064
[14:42:03] App: MEM:22.6% 29768/131064 12360-29632
[14:42:05] App: MEM:22.8% 30056/131064 12360-29928
[14:42:07] App: MEM:23.1% 30344/131064 12360-30216
[14:42:09] App: MEM:23.3% 30632/131064 12360-30504
[14:42:11] App: MEM:23.5% 30920/131064 12360-30792
[14:42:13] App: MEM:23.7% 31208/131064 12360-31080
[14:42:15] App: MEM:23.9% 31496/131064 12360-31368
[14:42:17] App: MEM:24.2% 31784/131064 12360-31656
[14:42:19] App: MEM:24.4% 32072/131064 12360-31944
[14:42:21] App: MEM:24.6% 32360/131064 12360-32232
[14:42:23] App: MEM:24.8% 32648/131064 12360-32520
[14:42:25] App: MEM:21.4% 28136/131064 12360-32520
[14:42:27] App: MEM:21.6% 28424/131064 12360-32520
[14:42:29] App: MEM:21.8% 28696/131064 12360-32520
[14:42:31] App: MEM:22.0% 29000/131064 12360-32520
[14:42:33] App: MEM:22.3% 29288/131064 12360-32520
[14:42:35] App: MEM:22.5% 29576/131064 12360-32520
[14:42:37] App: MEM:22.7% 29864/131064 12360-32520

Is my code wrong?

 

app/index.js

console.log('Hello world!');
import * as memoryMonitor from "./memoryMonitor";

memoryMonitor.initMemoryPressureMonitor();
memoryMonitor.start();

let mu=memoryMonitor.memUsageStart("index");

import * as document from "document";

let sectors=[
    "sun"   ,
    "cloud" ,
    "prec"  ,
    "wind"  ,
    "gust"  ,
    "ice"   ,
];  
setUi(0)

function setUi(from){
    for (let i=from;i<72;i++){
        let sectorUi=document.getElementById("s_"+i);
        let offset=0;
        for (let s=0;s<sectors.length;s++){
            let sector=sectors[s];
            let sect= sectorUi.getElementById(sector);
            //let arc=sect.getElementById("arc")

            //TODO set ui
            
            sect=null;
            //arc=null;
        };
        sectorUi=null
        if (i-from>2){
            setTimeout(()=>{
                setUi(i);
            },1);
            break;
        }
    }
}

mu("EXIT")
 
app/memoryMonitor.js
import { memory } from "system";

export function initMemoryPressureMonitor(){
    memory.monitor.onmemorypressurechange=()=>{
        let msg=`Mem is ${memory.monitor.pressure} ${(memory.js.used / memory.js.total * 100).toFixed(1)}%`;
        switch (memory.monitor.pressure){
            case "normal": console.log(msg); break;
            case "high": console.warn(msg); break;
            case "critical": console.error(msg); break;
        }
    }
}

let min=999999;
let max=0;
const memUsageEnabled=true;
const memUsageDetailsEnabled=true;
let lastMemUsage=0;
export function start(){
    memStats("start");
    setInterval( memStats,2000);
}

export function memStats(desc) {
    if (!desc) desc="";
    min=Math.min(min,memory.js.used);
    max=Math.max(max,memory.js.used);
    let msg = `MEM:${(memory.js.used / memory.js.total * 100).toFixed(1)}% ${desc} ${memory.js.used}/${memory.js.total}  ${min}-${max}`;
    console.warn(msg);
    return msg;
}

export function memUsageStart(id){
    if (!memUsageEnabled) return ()=>{};
    printMemUsage(id,"ENTER");
    return (desc)=>memUsage(id,desc);
}

function pad(s,len,filler){
    let diff=len-s.length;
    if (len>0){
        for (let i=0;i<diff;i++) s+=filler;
    }
    return s;
}
export function memUsage(id,desc) {
    if (!desc){
        printMemUsage(id,"EXIT");
    }else{
        if (!memUsageEnabled||!memUsageDetailsEnabled) return;
        printMemUsage(id,desc);
    }
}

function printMemUsage(id,desc){
    let currentMemUsage=memory.js.used
    let msg = pad(`MEM USAGE ${id}.${desc}`,40,'.') +
              pad(`${((currentMemUsage-lastMemUsage)/ memory.js.total * 100).toFixed(1)}%`,10," ")+`${(currentMemUsage / memory.js.total * 100).toFixed(1)}%  ${currentMemUsage} / ${memory.js.total}      `;
    console.error(msg);
    lastMemUsage=currentMemUsage
}
 
resources/index.svg
<svg>
  <defs>
    <symbol id="alert">
        
    </symbol>
    <symbol id="sector">
        <use id="sun" href="#alert" />
        <use id="cloud" href="#alert" />
        <use id="prec" href="#alert" />
        <use id="gust" href="#alert" />
        <use id="wind" href="#alert" />
        <use id="ice" href="#alert" />
    </symbol>

    <symbol id="alerts">
        <use href="#sector" id="s_0"/>
        <use href="#sector" id="s_1"/>
        <use href="#sector" id="s_2"/>
        <use href="#sector" id="s_3"/>
        <use href="#sector" id="s_4"/>
        <use href="#sector" id="s_5"/>
        <use href="#sector" id="s_6"/>
        <use href="#sector" id="s_7"/>
        <use href="#sector" id="s_8"/>
        <use href="#sector" id="s_9"/>
        <use href="#sector" id="s_10"/>
        <use href="#sector" id="s_11"/>
        <use href="#sector" id="s_12"/>
        <use href="#sector" id="s_13"/>
        <use href="#sector" id="s_14"/>
        <use href="#sector" id="s_15"/>
        <use href="#sector" id="s_16"/>
        <use href="#sector" id="s_17"/>
        <use href="#sector" id="s_18"/>
        <use href="#sector" id="s_19"/>
        <use href="#sector" id="s_20"/>
        <use href="#sector" id="s_21"/>
        <use href="#sector" id="s_22"/>
        <use href="#sector" id="s_23"/>
        <use href="#sector" id="s_24"/>
        <use href="#sector" id="s_25"/>
        <use href="#sector" id="s_26"/>
        <use href="#sector" id="s_27"/>
        <use href="#sector" id="s_28"/>
        <use href="#sector" id="s_29"/>
        <use href="#sector" id="s_30"/>
        <use href="#sector" id="s_31"/>
        <use href="#sector" id="s_32"/>
        <use href="#sector" id="s_33"/>
        <use href="#sector" id="s_34"/>
        <use href="#sector" id="s_35"/>
        <use href="#sector" id="s_36"/>
        <use href="#sector" id="s_37"/>
        <use href="#sector" id="s_38"/>
        <use href="#sector" id="s_39"/>
        <use href="#sector" id="s_40"/>
        <use href="#sector" id="s_41"/>
        <use href="#sector" id="s_42"/>
        <use href="#sector" id="s_43"/>
        <use href="#sector" id="s_44"/>
        <use href="#sector" id="s_45"/>
        <use href="#sector" id="s_46"/>
        <use href="#sector" id="s_47"/>
        <use href="#sector" id="s_48"/>
        <use href="#sector" id="s_49"/>
        <use href="#sector" id="s_50"/>
        <use href="#sector" id="s_51"/>
        <use href="#sector" id="s_52"/>
        <use href="#sector" id="s_53"/>
        <use href="#sector" id="s_54"/>
        <use href="#sector" id="s_55"/>
        <use href="#sector" id="s_56"/>
        <use href="#sector" id="s_57"/>
        <use href="#sector" id="s_58"/>
        <use href="#sector" id="s_59"/>
        <use href="#sector" id="s_60"/>
        <use href="#sector" id="s_61"/>
        <use href="#sector" id="s_62"/>
        <use href="#sector" id="s_63"/>
        <use href="#sector" id="s_64"/>
        <use href="#sector" id="s_65"/>
        <use href="#sector" id="s_66"/>
        <use href="#sector" id="s_67"/>
        <use href="#sector" id="s_68"/>
        <use href="#sector" id="s_69"/>
        <use href="#sector" id="s_70"/>
        <use href="#sector" id="s_71"/>
    </symbol>

</defs>


<use href="#alerts" id="alerts"/>

</svg>



 
Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

I'm afraid it's normal for getElement... to hold on to memory. My assumption is that it creates JS objects that correspond to the SVG elements it's applied to, and the system retains those objects internally so it doesn't have to recreate them every time getElement... is called for the same element.

 

I've found that I can't have many more than about 300 elements in a project (depending on code size). You seem to have at least 71*6 elements, so the issue could be as simple as that.

Peter McLennan
Gondwana Software

View best answer in original post

Best Answer
9 REPLIES 9

Hi @alessandroame  - presumably you are loading to a pre Versa 2 watch.

 

Garbage collection may not happen immediately.

 

There may be other issues raising the memory_err in SDK 4.3 that weren't there in SDK 4.2

 

Try in the OS Simulator 0.9.0 and see if the problem is resolved.

 

Something may be wrong with SDK 4.3

Author | ch, passion for improvement.

Best Answer
0 Votes

My environment:

  • sdk 6.0.2 
  • simulator 0.9.2 targeting sense
  • device sense

The scenario applies also to real device.

As you can see in the output @ [14:42:25] garbage collector was triggered

 

Best Answer
0 Votes

@alessandroame  if your program will work with it,  try using SDK 5 in your package.json, 

 

The same error may be in 6 that's in 4.3 as they were released together.

Author | ch, passion for improvement.

Best Answer

I'm afraid it's normal for getElement... to hold on to memory. My assumption is that it creates JS objects that correspond to the SVG elements it's applied to, and the system retains those objects internally so it doesn't have to recreate them every time getElement... is called for the same element.

 

I've found that I can't have many more than about 300 elements in a project (depending on code size). You seem to have at least 71*6 elements, so the issue could be as simple as that.

Peter McLennan
Gondwana Software
Best Answer

@Guy_ Same result with sdk5

 

Best Answer

@Gondwana  I agree with you but I was hoping I was wrong.

Best Answer
0 Votes

If you didn't need all of those elements available simultaneously, you might be able to use the document API to load a different .view. I think that would free memory allocated to previous elements, and it's the only way I suspect to do so.

But that probably won't suit your concept.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

I will find an other way.

Thanks to all for your posts.. you make the community alive, in the past it was a silent desert here.

Best Answer

There's also a community here.

Peter McLennan
Gondwana Software
Best Answer
0 Votes