jQuery UI Widgets Forums Gauges and Maps Gauges Memory leak in Gauge ?

This topic contains 1 reply, has 2 voices, and was last updated by  Hristo 3 years ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
  • Memory leak in Gauge ? #92508

    PAgenbag
    Participant

    Hi – I’m working with jqxWidgets in a dashboard type application that needs to run for significant periods of time continuously… however memory usage in the browser tab quickly gets out of hand and eventually crashes the tab with out of memory error.

    For reasons I wont go into here, I destroy and recreate the whole dashboard (with several jqXCharts on it) on each refresh .. which could be anywhere between a few seconds to a few minutes.

    After lots of digging around it appears to be caused (mostly) by detached svg nodes building up from recreating the charts regularly.

    I’m posting it in the gauge section , for testing I used a single gauge – but the problem seems to exist in other charts too.

    I created a minimal example that just destroys and recreates a single “static” gauge every 500ms , but soon the memory runs out of control.

    
    <!DOCTYPE html>
    <html>
    <head>
        <link type="text/css" rel="stylesheet" href="./bower_components/jqwidgets/jqwidgets/styles/jqx.base.css"/>
    
        <script type="text/javascript" src="./bower_components/jquery/dist/jquery.min.js"></script>
    
        <script type="text/javascript" src="./bower_components/jqwidgets/jqwidgets/jqxcore.js"></script>
        <script type="text/javascript" src="./bower_components/jqwidgets/jqwidgets/jqxdraw.js"></script>
        <script type="text/javascript" src="./bower_components/jqwidgets/jqwidgets/jqxchart.core.js"></script>
        <script type="text/javascript" src="./bower_components/jqwidgets/jqwidgets/jqxdata.js"></script>
        <script type="text/javascript" src="./bower_components/jqwidgets/jqwidgets/jqxgauge.js"></script>
    </head>
    
    <body class=''>
        <div id='chartContainer' style='overflow:hidden;width:400px;height:400px' class=''>
        </div>
    
        <script>
    
            var settings =
            {
                "ranges": [
                    {
                        "startValue": 0,
                        "endValue": 4,
                        "style": {
                            "fill": "#386e3f"
                        }
                    },
                    {
                        "startValue": 4,
                        "endValue": 8,
                        "style": {
                            "fill": "#6e6838"
                        }
                    },
                    {
                        "startValue": 8,
                        "endValue": 12,
                        "style": {
                            "fill": "#815b22"
                        }
                    },
                    {
                        "startValue": 12,
                        "endValue": 16,
                        "style": {
                            "fill": "#bb4141"
                        }
                    }
                ],
                "cap": {
                    "radius": 0.04
                },
                "caption": {
                    "offset": [
                        0,
                        -50
                    ],
                    "value": "Monitored 1 : Alarm 1",
                    "position": "bottom"
                },
                "value": 6,
                "style": {
                    "stroke": "#2a2a2a",
                    "stroke-width": "1px",
                    "fill": "#2a2a2a"
                },
                "animationDuration": 0,
                "labels": {
                    "visible": true,
                    "position": "outside",
                    "interval": 1
                },
                "min": 0,
                "max": 16,
                "startAngle": 0,
                "endAngle": 180,
                "radius": "50%",
                "border": {
                    "size": "0",
                    "visible": false
                },
                "ticksMinor": {
                    "interval": 1,
                    "size": "5%",
                    "style": {
                        "stroke": "#3c3b3b"
                    }
                },
                "ticksMajor": {
                    "interval": 2,
                    "size": "10%",
                    "style": {
                        "stroke": "#3c3b3b"
                    }
                },
                "width": "100%",
                "height": "100%"
            };
    
            var gauge = null;
    
            setInterval(function()
            {
                if (gauge)
                {
                    gauge.jqxGauge('destroy');
                }
    
                $('#chartContainer').empty();
                $('#chartContainer').append($('<div class="gauge"></div>'));
    
                gauge = $('#chartContainer div.gauge').jqxGauge(settings);
            },500);
    
        </script>
    </body>
    

    The destroy function seems to completely remove the charts div , which is why I end up having to add it back in each time.

    I cant figure out how to insert an image off my local pc , but if you do a timeline profile in chromes dev tool , you can see that even after garbage collection m, the number of nodes (and listeners) does not go down like the heap – but instead keeps climbing at a steady pace. Even the heap does not clear entirely , but that seems to be less of a problem. If you do 3 heap snapshots and then show the retained objects in snapshot 3 that was allocated between snapshot 1 & 2 , you can see a whole bunch of stuff thats still referenced by jqxBaseFramework.

    The tabs memory climbs with a few K per refresh , which isnt astronomical – but if you have 10 charts on the screen and you have to have the display running for days/weeks/months on end, that just wont work.

    I cant claim to be an expert regarding the garbage collector and internal js workings , but I’d like to think I’m not doing something idiotic in my minimal sample ?

    P.S. After some more tests – it seems as if , when I minimise the browser or simply switch to another tab , so that the one with the charts is not actively being rendered, the mem usage seems to drop down again. Again , I’m not familiar with exactly how the garbage collector does its thing – but seems like the detached nodes are being removed when the tab becomes inactive.

    Memory leak in Gauge ? #92558

    Hristo
    Participant

    Hello PAgenbag,

    I tested the presented example with Chrome Dev Tools, I ‘Take Heap Snapshot’ and it does not look to has a Memory Leak.
    Could you give more details how to reproduce it, I try this example in Vishal Studio and looks the same?
    I would like to suggest you just update the value for each one Gauge with .val() method.

    Best Regards,
    Hristo Hristov

    jQWidgets team
    http://www.jqwidgets.com

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.