1. #1
    Sencha Premium Member
    Join Date
    Nov 2008
    Posts
    57
    Vote Rating
    0
    mishoboss is on a distinguished road

      0  

    Default Heap gone huge because of Array

    Heap gone huge because of Array


    Hi, in my app I continuously create and destroy field items. However the Heap is getting bigger and bigger and the app gets laggy.

    I have attached listeners for deactivate and destroy all child items:
    Code:
    Ext.getCmp('card1').on('deactivate', function(oldCard) { Ext.getCmp('card1').removeAll(true); });
    Ext.getCmp('card2').on('deactivate', function(oldCard) { Ext.getCmp('card2').removeAll(true); });
    Is there something more to do? If the items have handlers attached, do they destroy too?

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    35,735
    Vote Rating
    756
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    I often listen for the activeitemchange on the wrapping component as usually I have a back button. This event sends the new item and old item in it's arguments.
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

  3. #3
    Sencha Premium Member
    Join Date
    Nov 2008
    Posts
    57
    Vote Rating
    0
    mishoboss is on a distinguished road

      0  

    Default


    Thank you for that suggestion. I did it, but the Heap keeps going larger and larger and the app gets slower:
    Code:
    Ext.getCmp('content').on('activeitemchange', function(container, newcard, oldcard, opts) { oldcard.removeAll(true); });
    I think there are other objects created that I don't remove. But I don't know why. This is the app - http://m-design.bg/sencha/. Click on the first 4 rows to go to other pages. This way the app creates and removes items. And here is the whole app code. I would be very thankful if you take a snap look at it and tell me if you see something wrong Thank you.

    Code:
    Ext.require(['Ext.Panel', 'Ext.Button', 'Ext.Toolbar', 'Ext.util.JSONP', 'Ext.dataview.ComponentView']);
    
    
    
    var UIobjects = new Object();
    var currentCard = "card1";
    var broadCrumb = new Array();
    
    function pushWidget(widget, container) {
        if (widget) {
            container.push(widget);
        }
    }
    
    function buildUIArray(json, type, parent) {
        if (json) {
    
    
    
    
            var container;
    
            if (type == 'page') {
                UIobjects[json.id] = new Array();
                container = UIobjects[json.id];
            } else if (type == 'frame') {
                parent.push(new Object({
                    xtype: 'fieldset',
                    title: json.label
                }));
                container = parent[parent.length - 1]['items'] = new Array();
            }
    
            var page_data = json.widget;
            if (Ext.isArray(page_data)) {
                for (var i in page_data) {
                    pushWidget(addsWidget(page_data[i], container), container);
                }
            } else {
                pushWidget(addsWidget(page_data, container), container);
            }
    
            json = null;
    
    
    
    
        } else {
            alert('There was an error retrieving the UI.');
        }
    }
    
    
    
    
    function addsWidget(data, container) {
        var widget;
        if (data.type == "Switch") {
            widget = new Object({
                xtype: 'togglefield',
                label: data.label
            });
        } else if (data.type == "Slider") {
            widget = new Object({
                xtype: 'sliderfield',
                label: data.label,
                value: data.item.state,
                minValue: 0,
                maxValue: 100
            });
        } else if (data.type == "Text") {
            widget = new Object({
                xtype: 'textfield',
                label: data.label,
                value: data.item ? data.item.state : data.label,
                readOnly: true
            });
        } else if (data.type == "Group") {
            widget = new Object({
                xtype: 'button',
                text: data.label,
                style: 'display:block',
                page_id: data.linkedPage.id,
                handler: tapHandler,
                baseCls: 'x-form-label x-field',
                labelCls: ''
            });
            buildUIArray(data.linkedPage, 'page', '');
        } else if (data.type == "Frame") {
    
            buildUIArray(data, 'frame', container);
        }
        return widget;
    
    }
    
    
    
    
    
    
    
    
    var tapHandler = function (btn, evt) {
            broadCrumb.push(btn.page_id);
            Ext.getCmp("content").getLayout().setAnimation({
                type: 'slide',
                direction: 'left'
            });
            goToPage(btn.page_id);
    
        }
    
    
    var goToPage = function (page) {
            if (currentCard == "card1") {
                currentCard = "card2";
            } else {
                currentCard = "card1";
            }
    
            Ext.getCmp(currentCard).setItems(UIobjects[page]);
            Ext.getCmp("content").setActiveItem(currentCard);
        }
    
    
    Ext.setup({
        tabletStartupScreen: 'tablet_startup.png',
        phoneStartupScreen: 'phone_startup.png',
        icon: 'icon.png',
        glossOnIcon: false,
    
    
    
    
    
        onReady: function () {
            //var server_url = 'http://192.168.90.176:8080';
            var server_url = 'http://m-design.bg/sencha';
    
    
    
    
            var backPage = function () {
                    if (broadCrumb.length > 1) {
                        broadCrumb.pop();
                        Ext.getCmp("content").getLayout().setAnimation({
                            type: 'slide',
                            direction: 'right'
                        });
                        goToPage(broadCrumb[broadCrumb.length - 1]);
                    }
                }
    
    
    
    
            var makeJSONPRequest = function () {
                    Ext.getCmp('content').setMask({
                        message: 'Loading...'
                    });
                    Ext.util.JSONP.request({
                        url: 'http://m-design.bg/sencha/json.txt',
                        //url: server_url+'/rest/sitemaps/demo',
                        callbackKey: 'jsoncallback',
                        params: {
                            key: Math.random()
                        },
    
                        callback: function (result) {
    
                            buildUIArray(result.homepage, 'page', '');
                            Ext.getCmp('content').unmask();
                            broadCrumb[0] = result.homepage.id;
                            //console.log(UIobjects);
                            Ext.getCmp(currentCard).setItems(UIobjects[result.homepage.id]);
                            result = null;
                        }
                    });
                };
    
    
    
    
    
            var panel = Ext.create('Ext.Panel', {
                layout: {
                    type: 'card',
                    animation: {
                        type: 'slide',
                        direction: 'left'
                    }
                },
                fullscreen: true,
                id: 'content',
                autoDestroy: true,
                animation: {
                    type: 'slide',
                    direction: 'left'
                },
                items: [{
                    id: 'card1',
                    scrollable: 'vertical',
                    autoDestroy: true
                }, {
                    id: 'card2',
                    scrollable: 'vertical',
                    autoDestroy: true
                }, {
                    docked: 'top',
                    xtype: 'toolbar',
                    ui: 'light',
                    items: [{
                        text: 'Back',
                        handler: backPage
                    }, {
                        xtype: 'spacer'
                    }, {
                        text: 'Load UI',
                        handler: makeJSONPRequest
                    },
    
                    ]
                }]
            });
            Ext.getCmp('content').on('activeitemchange', function (container, newcard, oldcard, opts) {
                oldcard.removeAll(true);
            });
    
    
        }
    });

  4. #4
    Sencha Premium Member
    Join Date
    Nov 2008
    Posts
    57
    Vote Rating
    0
    mishoboss is on a distinguished road

      0  

    Default


    I just can't get through this problem. I debug the app via Google Chrome. I take heap snapshots continuously and compare them. It seems that there are created way more Object, Array and String entries than deleted.


    I've done some changes since my previous post. I've attached listeners to the buttons with delegation and I also remove listeners from the old card on card change. I thought maybe listeners are my problem, but it seems they're not.

    Please, take a look at the app HERE
    Don't enter anything in the Server field, just press "Login", then select the Demo interface.

    And the code:
    Code:
    Ext.require(['Ext.Panel', 'Ext.Button', 'Ext.Toolbar', 'Ext.util.JSONP', 'Ext.dataview.ComponentView']);
    
    
    //-------- PATCH FOR BUTTON TO ACCEPT HTML TEXT -----------
    //----- won't be needed in the next Sencha releases -------
    Ext.define('Ext.overrides.button.updateHtml', {
        override: 'Ext.Button',
    
        updateHtml: function (html) {
            var element = this.textElement;
    
            if (html) {
                element.show();
                element.update(html);
            } else {
                element.hide();
            }
        }
    });
    //-------------------- END PATH -----------------------
    
    var UIobjects = new Object();
    var currentCard = "card1";
    var broadCrumb = new Array();
    var broadCrumbText = '';
    var server_url;
    
    
    
    
    
    
    
    
    
    var sitemapsStore = new Ext.data.Store({
        fields: ['name', 'link']
    
    });
    
    
    
    function showLoginWindow() {
        var login = Ext.create('Ext.Panel', {
            floating: true,
            modal: true,
            centered: true,
            width: '90%',
            height: 300,
    
            items: [{
                title: 'Login',
                xtype: 'toolbar',
                ui: 'light',
                docked: 'top'
            }, {
                xtype: 'urlfield',
                label: 'Server',
                id: 'server_settings',
                autoCorrect: true,
                placeHolder: 'http://localhost:8080',
                required: true,
                value: localStorage.getItem('openHAB_server')
            }, {
                xtype: 'textfield',
                label: 'Username',
                id: 'username_settings',
                placeHolder: 'username',
                disabled: true
            }, {
                xtype: 'passwordfield',
                label: 'Password',
                id: 'password_settings',
                placeHolder: 'password',
                disabled: true,
                style: 'margin-bottom:10px;'
            }, {
                xtype: 'button',
                text: 'Login',
                style: 'display: block; margin: auto; width:150px;',
                handler: function () {
                    server_url = Ext.getCmp('server_settings').getValue();
                    if (server_url.substring(0, 7) != "http://") {
                        server_url = "http://" + server_url;
                    }
                    localStorage.setItem('openHAB_server', server_url);
                    Ext.util.JSONP.request({
    
                        url: server_url + '/rest/sitemaps/jsonp',
                        //url: 'http://m-design.bg/sencha/sitemaps.txt',
                        callbackKey: 'jsoncallback',
                        headers: {
                            'Accept': 'application/json',
                        },
                        params: {
                            key: Math.random()
                        },
    
                        callback: function (result) {
                            login.destroy(true);
                            sitemapsStore.loadData(result.sitemaps);
                            showSitemapsWindow();
    
                        },
                        onFailure: function (result) {
                            console.log('error');
                        }
                    });
    
                }
            }]
        });
    
    
        Ext.getCmp('content').add(login);
    }
    
    
    function showSitemapsWindow() {
    
    
    
        var sitemapSelect = Ext.create('Ext.Panel', {
            floating: true,
            modal: true,
            centered: true,
            width: '90%',
            height: 300,
    
            layout: 'fit',
            scrollable: 'vertical',
            items: [{
                title: 'Interfaces',
                xtype: 'toolbar',
                ui: 'light',
                docked: 'top'
            }, {
                xtype: 'list',
                store: sitemapsStore,
                singleSelect: true,
                itemTpl: '{name}',
                onItemDisclosure: function (record, btn, index) {
                    loadUIData(record.data.link);
                    sitemapSelect.destroy(true);
                }
            }]
        });
    
        Ext.getCmp('content').add(sitemapSelect);
    
    
    }
    
    
    
    function loadUIData(url) {
        Ext.getCmp('content').setMask({
            message: 'Loading...'
        });
        Ext.util.JSONP.request({
    
            url: server_url + '/rest/sitemaps/demo/jsonp',
            //url,
            //url: 'http://m-design.bg/sencha/ui.txt',
            callbackKey: 'jsoncallback',
            headers: {
                'Accept': 'application/json',
            },
            params: {
                key: Math.random()
            },
    
            callback: function (result) {
    
                buildUIArray(result.homepage, 'page', '');
                Ext.getCmp('content').unmask();
                broadCrumb[0] = new Array(result.homepage.id, result.name);
                Ext.getCmp('title').setHtml(result.name);
                //console.log(UIobjects);
                Ext.getCmp(currentCard).setItems(UIobjects[result.homepage.id]);
                Ext.getCmp(currentCard).on({
                    delegate: 'button',
    
                    tap: tapHandler
                });
    
                result = null;
            }
        });
    };
    
    
    
    function backPage() {
        if (broadCrumb.length > 1) {
            broadCrumb.pop();
            Ext.getCmp("content").getLayout().setAnimation({
                type: 'slide',
                direction: 'right'
            });
            goToPage(broadCrumb[broadCrumb.length - 1][0]);
        }
    }
    
    function pushWidget(widget, container) {
        if (widget) {
            container.push(widget);
        }
    }
    
    function buildUIArray(json, type, parent) {
        if (json) {
    
    
    
    
            var container;
    
            if (type == 'page') {
                UIobjects[json.id] = new Array();
                container = UIobjects[json.id];
            } else if (type == 'frame') {
                parent.push(new Object({
                    xtype: 'fieldset',
                    title: json.label
                }));
                container = parent[parent.length - 1]['items'] = new Array();
            }
    
            var page_data = json.widget;
            if (Ext.isArray(page_data)) {
                for (var i in page_data) {
                    pushWidget(addsWidget(page_data[i], container), container);
                }
            } else {
                pushWidget(addsWidget(page_data, container), container);
            }
    
            json = null;
    
    
    
    
        } else {
            alert('There was an error retrieving the UI.');
        }
    }
    
    
    
    
    function addsWidget(data, container) {
        var widget;
        if (data.type == "Switch") {
            if (data.item.type == "RollershutterItem") {
                widget = createRollershutterWidget(data.label, data.icon, data.item.state)
            } else {
                widget = createToggleWidget(data.label, data.icon, data.item.state);
            }
    
        } else if (data.type == "Slider") {
            widget = createSliderWidget(data.label, data.icon, data.item.state);
    
        } else if (data.type == "Text") {
            if (data.linkedPage) {
                widget = createLinkWidget(data.label, data.icon, data.linkedPage.id, data.linkedPage.label);
                buildUIArray(data.linkedPage, 'page', '');
            } else {
                widget = createTextWidget(data.label, data.icon, data.item.state);
            }
        } else if (data.type == "Group") {
            widget = createLinkWidget(data.label, data.icon, data.linkedPage.id, data.linkedPage.label);
            buildUIArray(data.linkedPage, 'page', '');
    
        } else if (data.type == "Selection") {
            widget = createSelectionWidget(data.label, data.icon, data.item.state, data.mapping);
        } else if (data.type == "Frame") {
    
            buildUIArray(data, 'frame', container);
        }
        return widget;
    
    }
    
    
    
    
    
    
    
    
    var tapHandler = function (btn, evt) {
    
            broadCrumb.push([btn.page_id, btn.page_label]);
            Ext.getCmp("content").getLayout().setAnimation({
                type: 'slide',
                direction: 'left'
            });
            goToPage(btn.page_id);
    
        }
    
    
    var goToPage = function (page) {
            if (currentCard == "card1") {
                currentCard = "card2";
            } else {
                currentCard = "card1";
            }
    
            Ext.getCmp(currentCard).setItems(UIobjects[page]);
            Ext.getCmp("content").setActiveItem(currentCard);
        }
    
    
    
    
    
    
    
    
    
    
    Ext.setup({
        tabletStartupScreen: 'tablet_startup.png',
        phoneStartupScreen: 'phone_startup.png',
        icon: 'icon.png',
        glossOnIcon: false,
    
    
    
    
    
        onReady: function () {
    
    
    
            var panel = Ext.create('Ext.Panel', {
                layout: {
                    type: 'card',
                    animation: {
                        type: 'slide',
                        direction: 'left'
                    }
                },
                fullscreen: true,
                id: 'content',
                autoDestroy: true,
    
    
                items: [{
                    id: 'card1',
                    scrollable: 'vertical',
                    autoDestroy: true,
                    padding: 6,
                    cls: 'card1',
    
                }, {
                    id: 'card2',
                    scrollable: 'vertical',
                    autoDestroy: true,
                    padding: 6,
                    cls: 'card2',
    
                }, {
                    docked: 'top',
                    xtype: 'toolbar',
                    ui: 'light',
                    items: [{
                        id: 'back_btn',
                        ui: 'back',
                        text: 'Back',
                        handler: backPage,
                        hidden: true
                    }, {
                        xtype: 'spacer'
                    }, {
                        id: 'title',
                        xtype: 'label',
                        cls: 'oph_title'
                    }, {
                        xtype: 'spacer'
                    }
    
                    ]
                }]
            });
    
    
    
            Ext.getCmp('content').on('activeitemchange', function (container, newcard, oldcard, opts) {
                oldcard.removeAll(true);
                oldcard.clearListeners();
                newcard.on({
                    delegate: 'button',
    
                    tap: tapHandler
                });
                if (broadCrumb.length == 1) {
                    Ext.getCmp('back_btn').hide();
                } else {
                    Ext.getCmp('back_btn').show();
                }
                broadCrumbText = '';
                for (var k in broadCrumb) {
                    broadCrumbText += broadCrumb[k][1];
                    if (k != broadCrumb.length - 1) {
                        broadCrumbText += ' > '
                    }
                }
                Ext.getCmp('title').setHtml(broadCrumbText);
            });
            showLoginWindow();
    
    
        }
    });
    
    
    
    function createSliderWidget(label, icon, state) {
        return {
            xtype: 'sliderfield',
            label: '<img class="oph_icon" src="' + server_url + '/images/' + icon + '.png" />' + label,
            labelWidth: '60%',
            value: 45,
            minValue: 0,
            maxValue: 100
        };
    }
    
    function createTextWidget(label, icon, state) {
        return {
            xtype: 'textfield',
            label: '<img class="oph_icon" src="' + server_url + '/images/' + icon + '.png" />' + label.replace(/\[(.*?)\]/, ''),
            labelWidth: '60%',
            value: label.match(/\[(.*?)\]/)[1],
            readOnly: true
        };
    }
    
    function createToggleWidget(label, icon, state) {
        return {
            xtype: 'togglefield',
            label: '<img class="oph_icon" src="' + server_url + '/images/' + icon + '.png" />' + label,
            labelWidth: '60%',
            value: 1 //state == 'ON' ? 1 : 0
        };
    
    }
    
    function createRollershutterWidget(label, icon, state) {
        return {
            xtype: 'field',
            label: '<img class="oph_icon" src="' + server_url + '/images/' + icon + '.png" />' + label,
            labelWidth: '60%',
            html: '<div class="x-button-normal x-button x-layout-box-item oph_rollershutter_btn" style="margin-left:7px;"><span class="x-button-icon arrow_up x-icon-mask" ></span></div><div class="x-button-normal x-button x-layout-box-item oph_rollershutter_btn"><span class="x-button-icon delete x-icon-mask" ></span></div><div class="x-button-normal x-button x-layout-box-item oph_rollershutter_btn"><span class="x-button-icon arrow_down x-icon-mask" ></span></div>'
        };
    
    }
    
    function createLinkWidget(label, icon, page_id, page_label) {
        return {
            xtype: 'button',
            html: '<img class="oph_icon" src="' + server_url + '/images/' + icon + '.png" />' + label,
            style: 'display:block',
            baseCls: 'x-form-label x-field oph_group_btn',
            page_id: page_id,
            page_label: page_label,
            labelCls: ''
        };
    }
    
    function createSelectionWidget(label, icon, state, options) {
        return {
            xtype: 'selectfield',
            labelWidth: '60%',
            //value: state == "Undefined" ? options[1].command : state,
            label: '<img class="oph_icon" src="' + server_url + '/images/' + icon + '.png" />' + label,
            options: options,
            displayField: 'label',
            valueField: 'command'
        }
    };

  5. #5
    Sencha Premium Member
    Join Date
    Nov 2008
    Posts
    57
    Vote Rating
    0
    mishoboss is on a distinguished road

      0  

    Default


    OK, I have done some more tests and tried some more things based on what I've found on the Sencha forums.

    I have a Panel with a Card layout and with no items on initialize. Then I do this to change the card and load dynamic items content on that card:

    Code:
    sitemapUIpanel.setActiveItem(new Ext.Panel({scrollable: 'vertical', autoDestroy: true, padding: 6, items:UIobjects[page]}));
    The UIobjects array holds the items data in a ready to use format.


    I listen for activeitemchange event to destroy the old panel and attach button listeners to the new one:
    Code:
    sitemapUIpanel.onAfter('activeitemchange', function (container, newcard, oldcard, opts) {
    
        if (oldcard) {
            setTimeout(function () {
    
    
                oldcard.clearListeners();
                oldcard.destroy();
                console.log(oldcard);
                console.log(Ext.query('*').length);
            }, 1000);
    
        }
    
        newcard.on({
            delegate: 'button',
    
            tap: tapHandler
        });
    }, sitemapUIpanel);
    The result is even more tragic than before...
    There are thousands of new Arrays and Objects on every page created that are not deleted on destroy(). Could anyone give me some advise where I'm wrong?

  6. #6
    Sencha Premium Member
    Join Date
    Nov 2008
    Posts
    57
    Vote Rating
    0
    mishoboss is on a distinguished road

      0  

    Default


    Anyone?

Thread Participants: 1

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar