22

Before I start this question, I understand that every aspect of it is wrong. Please keep that in mind...

I have an CRM-ish intranet application with an integrated soft phone developed in 2001 that I've inherited. It's basically a collections application that integrates telephony controls with a web-based front end for account management. (Genesys telephony and an AS400-based collections system...using MQSeries)

I'm trying to modernize this application as much as I possibly can before I call it "end of life". As part of my attempts to modernize it, I've implemented jQuery & jQuery UI for my JS functionality and UI. I'm not going crazy with it, but it is pretty well ingrained.

Now, enter the problem: we currently use IE6 and the application is built using frames. The implementation of the jQuery libraries has exposed the sieve-like nature of the application from a memory perspective. It's currently consuming about 75Mb of memory on start up and grows to anywhere from 150Mb - 300Mb after about 2-3 hours. Then the browser crashes.

I've narrowed the memory leaks down to the cross-talk between the frames. I've tested the pages individually in sIEve and Drip and there are no leaks found. But access the pages within the frameset and it's a time bomb.

I know the answer is to redesign the application without frames and start using a better browser. There are two problems with that:

  1. I've tested this on IE9 and the issues are still there, but a little more controlled

  2. Redesigning the application would take about $500k and 6-12 months.

Does anyone know a way to resolve the "frame leak" issue? I know I haven't given any code examples but I'm just looking for general knowledge. I'm calling the IE CollectGarbage() method at onload and onunload for every page in the application but to no avail. I've tried calling the empty() method in jQuery. I've tried setting every child of the document.body element to null. Nothing is working.

I'd hate to have to back out all of these changes because there are actually some pretty large cost-cutting features that have been implemented.

ADDITIONAL INFO

I've managed to pinpoint the scenario in which the memory leaks occur. I thought it was "cross-talk" between frames but it seems that the memory leaks occur when a single frame is refreshed.

I set up a basic frameset with a 5 instances of the same page (one that I'm pretty sure has no leaks per sIEve).

<html>
    <head>
        <title>Frame Leak Test</title>
    </head>
    <frameset cols="*" rows="50%,50%" frameborder="1">
        <frameset cols="33%,33%,34%" rows="100%">
            <frame src="http://npasappgeneqa02/live/" />
            <frame src="http://npasappgeneqa02/live/" />
            <frame src="http://npasappgeneqa02/live/" />
        </frameset>
        <frameset cols="50%,50%" rows="100%">
            <frame src="http://npasappgeneqa02/live/" />
            <frame src="http://npasappgeneqa02/live/" />
        </frameset>
    </frameset>
</html>

The index page that is being loaded shows no leaks in sIEve.

When I load the frameset page in sIEve and click auto-refresh, there are no memory leaks reported. However, if I right-click -> refresh on an individual frame, 75% of the loaded items in the DOM get listed as leaks.

Obviously, the auto-refresh is equivalent to the F5/shift+F5 refresh. And that cleans out the memory for the page. But when an individual frame is reloaded, the memory never clears out...apparently. And every screen that my users have to see reloads into the main frame.

I can't simply refresh the frameset because there is a softphone in the frameset that will bring about Armageddon if it is refreshed or logged out of improperly.

Does anyone know of a way to control frameset memory without refreshing it?

Doug Weaver
  • 1,581
  • 2
  • 9
  • 8
  • 11
    For cramming the most different possible forms of wrong into a single post for the day and *knowing it*, you win an upvote. Congratulations. And sorry you have to put up with this :( – BoltClock Mar 09 '12 at 14:42
  • http://www.sencha.com/forum/showthread.php?36889-Memory-Leak-in-IE-while-using-Frames looks like someone who found a solution to a similar problem. Perhaps that would help? Likewise, http://stackoverflow.com/questions/2312800/ie6-memory-leak-on-refresh looks like id might have a few pertinent ideas - specifically the ones about making sure that IE6 is fully patched and writing the javascript from scratch rather than depending on JQuery. – Ben Barden Mar 09 '12 at 15:45
  • @BoltClock - Thanks for the sympathy. I'm tempted to break this thing apart and set the whole thing up on iframes and AJAX calls. – Doug Weaver Mar 09 '12 at 19:32
  • @BenBarden - I think that pertains specifically to the Ext.js library (which is pretty good looking). I've got quite a bit of JS over jQuery in there, but there are just some things that are just easier in jQuery. This whole thing has been a "learn as you go" kind of experience. – Doug Weaver Mar 09 '12 at 19:36
  • The more general issue (at least one of them, at least from what I could pick up) seems to be that JQuery has a habit of circular references and the older forms of IE are really bad at collecting those. I totally understand about how JQuery makes a lot of stuff easier, though. – Ben Barden Mar 09 '12 at 19:55
  • 1
    I don't have an answer, I just want you to know I feel bad for you. – Mike Robinson Mar 09 '12 at 22:06
  • 1
    +1 for a high quality, lucid, well explained question. (Oh, and good luck!) – random_user_name Mar 12 '12 at 14:25
  • You mention "use a better browser" and then put IE9 in the same perspective, haha, hilarious :) Internet would be a much better place is MS stopped releasing that piece of crap :D – ZolaKt Mar 12 '12 at 15:50
  • @ZolaKt - in the corporate world, IE9 _IS_ the better browser. As much as I've lobbied for Chrome, it just ain't happening. Alas...I'm stuck in an IE nightmare where my best hope is to escape with at least a shred of my dignity intact. :) – Doug Weaver Mar 13 '12 at 08:31
  • Btw. Douglas Crockford has written an article about this subject. http://javascript.crockford.com/memory/leak.html. He has a workaround, but not very useful. You would have to purge everything on every innerHTML change. Maybe doable if you do everything yourself, but if you use 3rd party controls like Telerik, ExtJS, almost any jQuery plugin... not very useful – ZolaKt Mar 13 '12 at 17:16
  • @lyrix191: Yes, only if you use other MS technologies. As usual, MS fixes their bugs with more bugs. That is where IE fits perfectly :) Just because they want you to use it doesn't make it right. Agreed, Chrome is nice but misses some things here and there, but still way better than IE. Firefox and Opera simply can't compare to that crap :P They are decent browsers. IE is just IE, the worst browser ever build, which is slowing down web developers for years. Anyway I wish you the best of lock. You will need it :D – ZolaKt Mar 13 '12 at 17:20

3 Answers3

2

Just wanted to give an update on this particular situation. I think that I've found an acceptable solution to this memory leak issue:

  1. Instead of using the full jQueryUI library on pages where UI elements were needed, I used the individual minimized scripts (uicore + datepicker, etc).
  2. Wherever possible, I avoided UI elements that utilized the widget script as this is where the largest concentration of issues arose.
    • a. This caused me to have to write custom scripts for button elements and the accordion element.
  3. Since this application runs in a frameset, utilizing window methods (ie, window.onload, window.onunload) don't work as the window itself only loads or unloads with the frameset. To combat this, I implemented document.body methods, specifically, document.body.onbeforeunload and doing a global unbind to remove any references that were hanging out ($("*").unbind();).

With the methodology utilized above, my 4-hour memory consumption in IE6 (and IE8) has dropped from ~200-250Mb to ~80-95Mb. My goal was to keep 8-hour consumption under 150Mb and I think this will accomplish the task.

Thanks to everyone for all of your help.

Doug Weaver
  • 1,581
  • 2
  • 9
  • 8
2

You posted no code to judge this from...but many of these scenarios result from improper use of closures.

Reading includes, but is not limited to:

Community
  • 1
  • 1
Prisoner ZERO
  • 13,848
  • 21
  • 92
  • 137
  • @Prizoner ZERO - I didn't post code because the issue systemic. Plus, since it's an custom intranet application, I'm limited. But your point is well taken. The only closures introduced are those inherent to jQuery. I could go back and handle the events myself, but I don't think that'd change much. Thanks for the references. – Doug Weaver Mar 13 '12 at 08:33
  • 1
    Look for situations where you might be binding (or rebinding) the same event(s) for a single control multiple times without first unbinding said control...this is more common than you might think. – Prisoner ZERO Mar 13 '12 at 11:21
  • Sounds logical. I'll give that a look. Thanks. – Doug Weaver Mar 13 '12 at 14:41
0

I would suggest running your JS code through either JSLint or JSHint.

These two utilities(*) are code quality checkers for Javascript. The things they complain about are where the JS code is valid but contains poor programming practices.

There's a good chance that they'll pick up at least some of the things that are causing you problems.

(* JSHint is a fork of JSLint, but they're sufficiently different now that it's worth trying them both)

Spudley
  • 166,037
  • 39
  • 233
  • 307