1

everybody! I'm working on some kind of an event calendar and I am using jQuery for the front-end and PHP for the back-end. I have all calendar data created with PHP and sent to the client, JSON-encoded.

Consider the following code (simplified):

    jQuery(document).ready(function($) {

    // property which contains calendar object 
    this.Calendar; 
    // get calendar object 
    show_month();

    /* Assign a click event to the next month button */

    $('#cal_month .next span').live('click', function() {
        var month = $(this).attr('id');
        var year  = $(this).attr('class');
        show_month(month, year);
    });

    function show_month(month, year) {
        // delete pointers to the current month object
        window.Calendar = undefined;
        // get new month object
        window.Calendar = get_month(month, year);

        /* doing some stuff with this object here, like output to the 
           document etc., no event bindings */
    }

    function get_month(month, year) {
        var calendar;
        $.ajax({
            type: 'GET',
            dataType: 'json',
            async: false,
            timeout: 100,
            url: '../some_url.php?month='+month+'&year='+year,
            success: function(result) { calendar = result; }
        });
       return calendar;
    }

    var counter = 0;
    while (counter != 1000) {
        $('#cal_month .next span').trigger('click');
        counter ++;
    } 
});

Switching months manually as well as making a loop results in a huge memory leak. I've read a bunch of info about memory leaks, js closures etc. here and generally on the internet but I guess I still have some misunderstanding. I's be glad to get some ideas about what is wrong in my code.

UPDATE

I am measuring memory usage watching firefox.exe (other browsers have the same trouble) in Task Manager. Memorry doesn't free even when I navigate from page. And after some time, it causes a great performance drop as I can make it use 600+ Mb.

I also have written a loop to switch months (added code above).

UPDATE 2

The reason I used global was that in my event calendar I also have week and day views, so I want an active month object to be available for functions that take care of those two views, and only destroy it and get the new one when user switches the month. My issue was exactly the usage of globals. That one solved, now trying to figure out how to keep an object available until user explicitly switches the month...

BTW, I've created a while loop for benchmarking purpose only, it has nothing to do with my actual code.

noname
  • 551
  • 9
  • 29
  • Why is `Calendar` global? Just declare it as `var Calendar;` and reference it elsewhere as `Calendar` instead of `window.Calendar`. There's also no need to assign `Calendar = undefined;` immediately before you assign it to a new value. – Matt Ball Apr 08 '11 at 14:34
  • 1
    I don't see any memory leaks, but I could be wrong. An example page (or more of the code) would be helpful so we can test it. – tcooc Apr 08 '11 at 14:39
  • 4
    How exactly are you measuring memory use? – Pointy Apr 08 '11 at 14:40
  • @MattBall That's logical, and that's what I've written first, but this had the same effect, and that was when I started to wrap my mind about pointers to object, garbage collector and stuff, and came up with probably even more wrong decision. – noname Apr 08 '11 at 14:59
  • I'm wondering if the event handlers aren't getting destroyed when you are cycling through the months. I found this - http://stackoverflow.com/questions/2316726/javascript-memory-leaks , which may be of some help. – Amy Anuszewski Apr 08 '11 at 15:01
  • Are you running Firebug while testing memory consumption? This will skew the results, especially if you're using the Network tab, because that tab tracks **every** request. With multiple ajax calls, you can only expect to see linearly increasing memory consumption. **Make sure that Firebug is closed and disabled when testing.** – Matt Ball Apr 08 '11 at 15:16

5 Answers5

4

I'm curious to know why you think there is a memory leak issue. There are two other big issues that I see that are unrelated to memory, but are perhaps more important.

The first problem is the synchronous server call. You should in principal never use a synchronous call, because it locks the browser while the request is in progress. EDIT: doing this 1000 times in that loop will lock the browser for up to 1000 * 100 milliseconds, which will cause some, shall we say, user experience issues.

Second is the global Calendar object. Aside from relying on confusing global state, you make it impossible to do simple things like have 2 calendars on the same page.

This code below fixes those two issues.

jQuery(document).ready(function($) {

    $('#cal_month .next span').live('click', function() {
        var month = $(this).attr('id');
        var year  = $(this).attr('class');
        generate_calendar(month, year);
    });

    generate_calendar();

    function calendar_fetch_complete(result) {
        var calendar = result;

        /* doing some stuff with this object here, like output to the 
           document etc.*/
    }

    function generate_calendar(_month, _year) {
        var month = _month || (new Date().getMonth() + 1),
            year  = _year  || (new Date().getYear() + 1900);
        $.ajax({
            type: 'GET',
            dataType: 'json',
            url: '../some_url.php?month='+month+'&year='+year,
            success: calendar_fetch_complete
        });
    }

});
EMI
  • 816
  • 5
  • 9
2

i will suggest to use tools like http://www.dynatrace.com/en/ they really help at times.

Check this article http://ejohn.org/blog/deep-tracing-of-internet-explorer/ from John Resig himself.

Try following firebug trick: I would suggest you to try one more thing. Simple firebug trick. When you are not using/mouse operations on the UI control just click on the profiling button of the firebug. see how many of the functions and there calls are happening see if something is ODD and taking real long time. Its good simple trick but help crack issues like these ... :)

http://getfirebug.com/logging

Understanding Firebug profiler output

Community
  • 1
  • 1
Anil Namde
  • 6,452
  • 11
  • 63
  • 100
1
var counter = 0;
while (counter != 1000) {
    $('#cal_month .next span').trigger('click');
    counter ++;
} 

What? According to this code, you are triggering multiple span elements 1000 times, and requesting synchronous JSON for each of these elements 1000 times, which rewrites a single global variable. This is not a memory "leak", it's exhaustion.

I suggest refactoring your code to include asynchronous requests and taking out that while loop.

tcooc
  • 20,629
  • 3
  • 39
  • 57
0

You say there is a memory leak, but how are you determining this?

It may be that you're just looking at the browser process memory usage. Whatever the browser does with memory isn't necessarily related to what you're doing in the javascript. It may be that the javascript engine doesn't let go of memory space that it thinks it will use again -- whether you're currently using it or not.

Please find the right tools to analyze this and/or provide more information about why you think there is a memory leak.

John Fisher
  • 22,355
  • 2
  • 39
  • 64
  • Thanks for your answer, maybe you could give an advise, which is a good tool to use. – noname Apr 08 '11 at 15:03
  • @noname: I have only needed the debugging tools found in the various browsers. Other than that, I have no recommendations. – John Fisher Apr 08 '11 at 15:31
0

while (counter != 1000) { $('#cal_month .next span').trigger('click'); counter ++; }

This looks like you are assigning 1000 triggers to something- can't you handle any clicks from a parent object?

kennebec
  • 102,654
  • 32
  • 106
  • 127