Ajax request consumes huge memory (1GB+) for big responses
Reported by Rodrigo Rosauro | May 29th, 2008 @ 03:59 PM | in 1.6.1
I'm using "Ajax.Request" to get a big (4 MB) XML file from the server with Firefox (2 and 3RC1) and prototype.js 1.6.0.2.
Every time this ajax call is performed, the browser hangs for around a minute and the memory consumption grows up to ~1GB.
At first I thought this was a FF problem, but just to be sure I tested using only the native XMLHttpRequest object, getting for my surprise an absolutely instantaneous response without any visible memory consumption.
After some investigation I found that the cause of the problem relies on line #1361 (the Ajax.Response constructor). Here follows the problematic code:
if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = String.interpret(transport.responseText); // <- problem
this.headerJSON = this._getHeaderJSON();
}
Since Firefox sends a "readyState" 3 for every 4096 bytes read, the "transport.responseText" property is accessed many times during the request execution, and every time this native property is accessed, the browser needs to create a new (big) JavaScript String instance with its contents.
In order to fix MY problem, I just removed the verification of readyState 3 (because I don't need any data when this status arrives), but a more general solution could be to just move line #1361 to the next "if" (which checks explicitly for readyState 4.
My final code (modified):
Ajax.Response = Class.create({
initialize: function(request){
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if(readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = String.interpret(transport.responseText);
this.headerJSON = this._getHeaderJSON();
var xml = transport.responseXML;
this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
Proposed general-solution code:
initialize: function(request){
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.headerJSON = this._getHeaderJSON();
}
if(readyState == 4) {
this.responseText = String.interpret(transport.responseText);
var xml = transport.responseXML;
this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
Comments and changes to this ticket
-
Juriy Zaytsev May 29th, 2008 @ 07:57 PM
- → State changed from new to enhancement
- → Milestone changed from to 1.6.1
-
Tobie Langel May 30th, 2008 @ 01:34 AM
- → State changed from enhancement to bug
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
The Prototype JavaScript library.
