search envelope-o feed check
Home Unanswered Active Tags New Question
user comment-o

Leaking problem

Asked by Jan Marten
12 years ago.
Hi Dan,

We are using the scheduler control in combination with ajax.NET. It seems that this combination leads to a great memory leak. Could you have a look at this problem?

If you need a sample I could send you one by e-mail.

Kind regards,

Jan Marten
Comment posted by Dan Letecky
12 years ago.
Hi Jan. The problem of DayPilotScheduler is that it generates enormous amount of code (especially for the year view). When using the callbacks, only the events are redrawn but when using an UpdatePanel everything gets redrawn after update.

I would like to take a look at the memory leak as part of the on-demand loading option (scheduled for 4.4 release).
Comment posted by Jan Marten
12 years ago.
Addendum;

After examining the current 'problem' I have found that the server response after a post-back is generating 1.7 MB *) of data to the client (wow). This is for a month-view with a scheduler with 25 resources and around 900 events. Total time to render in develop-mode ~ 2,5 minutes. With IIS7 on Vista it takes half that time.

All this is not that kind of a problem. The problem is that browsers do not free their memory after a postback occured. A month view easily consumes 15 MB of memory with each click. So I am not sure if this problem is specific to DayPilot or to Ajax.NET. I have been looking into javascript leakings as mentioned here on MSDN. But this didn't fix the problem.

*) - Viewstate is around 1,3 MB, the rest is taken up by, what looks like, HTML.


Further description of the website; Scheduler, next, current, prev buttons for date selection, a calendar control, a bunch of jQuery/Highslide-code.
Comment posted by Dan Letecky
12 years ago.
I'm aware of the limitations of the current scheduler. It's not ready to show 900 events at the moment. If rendering takes more than a couple of seconds, the user comfort goes down to zero. That's why the on-demand loading is in the spec of the next release (4.4). It should help a lot in scenarios like yours - it will always draw (and load) only the events for the visible viewport. Not only it will help in the CallBack scenarios but it will also help for PostBack or partial PostBack (inside an UpdatePanel).

I've investigated the possible leak sources and it seems to be related to references between the DOM objects and other JavaScript objects on the page (these are separate domains in IE and it is causing problems), especially the event handlers (div.onclick = function() { ... } ). The leak itself won't be eliminated by the on-demand loading but its effect will be minimized (not so much memory leaking).

I will also focus especially on eliminating the leaks as the next step.

The ViewState size is a similar problem. It's so big because all the event data are stored there. If you are using CallBacks only, you can safely turn ViewState off. You could turn it off for PostBacks as well but you will need to set all programmatically changed properties and call DataBind() during each PostBack. I could make it more tunable by adding a special option for not storing the event data in the ViewState but I'm afraid it would only make the API too complicated.
Comment posted by Phillippe
12 years ago.

Hi,

Is there any update on this memory leak? We have used DayPilot Scheduler extensively throughout our web application and since rollout we have found this leak to be a major problem. I've found using sIEve that {dayPilot}_scroll, {dayPilot}_main tags and the top resource header DIV are being leaked. One instance of each for every time that the daypilot markup that has come down in our UpdatePanel; however I cannot work out a method of releasing them. The worst bit is that it seems to be leaking the entire page's memory along with these tags. This wouldn't be too much of an issue, however we have clients (with extremely old machines) running the application over cytrix. This results in speed issues for every cytrix user as the "client"s are all eating up the cytrix server's memory at the same time.

NB: We're using IE6 and ASP.Net 2.0.

Our reason for using UpdatePanels instead of using DayPilot's callback functions is that these functions do not cope with changes in slot length &resources etc (basically all the markup). So I am wondering whether you plan to make daypilot capable of rendering the markup completely client-side?

Thanks in advance. P.S. I realise my tone in a bit ranty, but apart from the memory leak, Ithink the control is second to none for scheduling. Keep up the good work.

Phil.

Comment posted by Dan Letecky
12 years ago.
Phil,

Thanks for reminding this issue. I'm trying to give performance issues the highest priority - I've added this problem to the DayPilot Pro 4.9 todo list (rescheduled to June 5, 2008).
Comment posted by Phillippe
12 years ago.

Hi,

I managed to find the leaks inthe end. In the latest updates to IE6 MS says that they have fixed the circular reference (from DOM to javascript & vice versa) causing leaks problem, however I then found that that only counts for elements still attached to the document. When an UpdatePanel refreshes, the contents are removed from the DOM and so the leaks persist. I then found this article (NB: I'm new to this JS leak stuff, so the content of this link may be old hat to most) http://javascript.crockford.com/memory/leak.html. I adapted the brute force cleanup code in this article to output a quasi-xpath stringto a textbox containingthe locations of all handlers it finds under the DayPilot markup.

Here's the modified brute force code... supply d = DayPilot DIV, path = "".

function purge(d, path) 
{
var a = d.attributes, i, l, n;
var tb = document.getElementById('<% =Console.ClientID %>');

if (a)
{
l = a.length;
for (i = 0; i < l; i += 1)
{
n = a[i].name;

if (typeof d[n] === 'function')
{
if (d[n] != null)
tb.text += path + '.' + n + '()' + '\n';

d[n] = null;
}
}
}

a = d.childNodes;
if (a)
{
l = a.length;
for (i = 0; i < l; i += 1)
purge(d.childNodes[i], ((d.childNodes[i].id != null && d.childNodes[i].id != '') ? d.childNodes[i].tagName + '[@id=\'' + d.childNodes[i].id + '\']' : path + '.' + d.childNodes[i].tagName));
}
}

From the output I then wrote the following cleanupDayPilotHandlers function which should be calledbefore refreshing an update panel containing DayPilot. I guess it would have to be modified if it's to be called before a call back (by the way this leaks too, but only when the number of columns change).

function getFirstChildByTagName(parent, childTagName) 
{
var child = parent.firstChild;
while(child!=null)
{
if (child.tagName == childTagName)
return child;

child = child.nextSibling;
}

return null;
}
//dayPilot is the javaScript dayPilot instance eg. dpc1.
function cleanupHandlers(dayPilot)
{
dayPilot.selectedEvents = [];
var dayPilotName = dayPilot.id;

var header = document.getElementById(dayPilotName + '_header');
var scroller = document.getElementById(dayPilotName + '_scroll');
var main = document.getElementById(dayPilotName + '_main');
var events = document.getElementById(dayPilotName + '_events');

var headerTBody = getFirstChildByTagName(header, 'TBODY');
var headerTR = getFirstChildByTagName(headerTBody, 'TR');
headerTD = headerTR.firstChild
while (headerTD != null)
{
if (headerTD.tagName == 'TD')
headerTD.onclick = null;

headerTD = headerTD.nextSibling;
}

scroller.onscroll = null;

main.onmouseup = null;
main.onmousemove = null;

eventsTD = events.firstChild;
while (eventsTD != null)
{
if (eventsTD.tagName == 'TD')
{
var outerDIV = getFirstChildByTagName(eventsTD, 'DIV');

var innerDIV = outerDIV.firstChild;

while (innerDIV != null)
{
if (innerDIV.tagName == 'DIV')
{
innerDIV.data = null;
innerDIV.event = null;
innerDIV.oncontextmenu = null;
innerDIV.onmousemove = null;
innerDIV.onmousedown = null;
}

innerDIV = innerDIV.nextSibling;
}
}

eventsTD = eventsTD.nextSibling;
}

var mainTBody = getFirstChildByTagName(main, 'TBODY');
var mainTR = mainTBody.firstChild;
while (mainTR != null)
{
if (mainTR.tagName == 'TR')
{
var mainTD = mainTR.firstChild;

while(mainTD != null)
{
if (mainTD.tagName == 'TD')
{
mainTD.onmouseup = null;
mainTD.oncontextmenu = null;
mainTD.onmousemove = null;
mainTD.onclick = null;
mainTD.root = null;
}

mainTD = mainTD.nextSibling;
}
}

mainTR = mainTR.nextSibling;
}
}

NB: I'm not sure that this is exhaustive as we're only using a limited set of features (basically displaying a schedule, selecting an event and selecting time ranges), so if you find more memory leaks, use the purge function above to track them down.

Regards,

Phil.

Comment posted by Dan Letecky
12 years ago.
This is awesome! Thanks for investing your time in this issue.
Comment posted by Dan Letecky
12 years ago.
The memory leak was fixed in DayPilot Pro 4.9 SP1.
Comment posted by Witwicky
11 years ago.

Hi Dan,

I am using DaypilotScheduler version 5.0 with Latest Service Pack. I have about about 300 resources and 700 events in a dayview.The IE memory usagestarts with 40 MB and goes upto 1 GB after 5 to 6 hours.The dayview refreshes after every 5 mins.As told by you the leaking problem has been fixed in version 4.9.Any help would be much appriciated.

This question is more than 3 months old and has been closed. Please create a new question if you have anything to add.