#124 bug
Rodrigo Rosauro

Ajax request consumes huge memory (1GB+) for big responses

Reported by Rodrigo Rosauro | May 29th, 2008 @ 03:59 PM | in After 1.7

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

    Juriy Zaytsev May 29th, 2008 @ 07:57 PM

    • Milestone set to 1.7
    • State changed from “new” to “enhancement”
  • Tobie Langel

    Tobie Langel May 30th, 2008 @ 01:34 AM

    • State changed from “enhancement” to “bug”
  • eno

    eno November 16th, 2008 @ 02:16 PM

    • Tag set to ajax, needs_patch, needs_tests

    I run into the same problem, in similar circumstances. Now even though the OP's original workaround would fix that problem, I would appreciate fixing

    String.interpret(transport.responseText);

    instead. As this is not exactly documented - and may be not part of the official API - I take it it is meant to convert some invalid values into empty strings and leave strings unchanged. Firefox, however, seens to always create new string objects. See #447

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 01:54 AM

    • Tag changed from ajax, needs_patch, needs_tests to needs_patch, needs_tests, section:ajax

    [not-tagged:"ajax" tagged:"section:ajax" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 02:26 AM

    • Tag changed from needs_patch, needs_tests, section:ajax to missing:tests, needs_patch, section:ajax

    [not-tagged:"needs_tests" tagged:"missing:tests" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 02:28 AM

    • Tag changed from missing:tests, needs_patch, section:ajax to missing:patch, missing:tests, section:ajax

    [not-tagged:"needs_patch" tagged:"missing:patch" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 03:36 AM

    • Tag changed from missing:patch, missing:tests, section:ajax to missing:patch, needs:tests, section:ajax

    [not-tagged:"missing:tests" tagged:"needs:tests" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 03:37 AM

    • Tag changed from missing:patch, needs:tests, section:ajax to needs:patch, needs:tests, section:ajax

    [not-tagged:"missing:patch" tagged:"needs:patch" bulk edit command]

  • T.J. Crowder

    T.J. Crowder November 16th, 2009 @ 04:50 PM

    [responsible:none bulk edit command]

  • Andrew Dupont

    Andrew Dupont October 19th, 2010 @ 03:49 AM

    • Milestone changed from 1.7 to After 1.7
    • Assigned user set to “Tobie Langel”
    • Importance changed from “” to “Medium”

    It's too late to change this for 1.7, but we're planning to address a bunch of Ajax issues sometime soon after 1.7. Pushing this back.

  • viovio26

    viovio26 February 5th, 2019 @ 03:16 PM

    rail rush mod apk Have you checked the latest Rail Rush game? ... Yes, you can make the game more interesting by using our Rail Rush Mod Apk. ... Also check out Shadow Fight 2 mod apk for unlimited gems, points and weapons.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

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.

Shared Ticket Bins

Referenced by

Pages