Is Internet Explorer 9 (IE9) leaking during ajax / web service calls? - ajax

I think I may have discovered quite a bad memory leak in Internet Explorer 9. It seems that when doing AJAX calls to a web service, IE9 leaks memory each time. In fact it seems to leak more memory than the size of the transfer involved.
If you watch the IE9 process in task manager you see the memory usage climb (and never fall). The browser eventually uses ~1.5GB of memory at which point the application crashes. Obviously this would be a problem if you are trying to develop an AJAX web app that is meant to stay running for days at a time.
This behaviour does not occur on IE8, Chrome or Firefox. I have also tested IE9 with all addons disabled.
Below is some ASP.NET 2.0 code that can reproduce the problem (you will need the MS ASP.NET AJAX extensions if you wish to try it):
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebServiceLeakTest._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Web Service Leak Test</title>
<script type="text/javascript" src="jQuery-1.7.js"></script>
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
resultsArea = jQuery("#results");
resultsArea.html(iterationCount);
GetData();
});
var resultsArea;
var iterationCount = 0;
var useJQuery = false;
var waitInterval = 1500;
function GetData()
{
if(useJQuery)
{
$.ajax(
{
url: "TestWebService.asmx/GetSomeData",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: ReceiveData,
error: ReceiveError
});
}
else
{
WebServiceLeakTest.TestWebService.GetSomeData(ReceiveData, ReceiveError);
}
}
function ReceiveData(data)
{
resultsArea.html(iterationCount++);
setTimeout(GetData, waitInterval);
}
function ReceiveError(error)
{
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="TestWebService.asmx" />
</Services>
</asp:ScriptManager>
<div id="results">
!
</div>
</form>
</body>
</html>
You will notice from the code that the results returned from the web service call are not even stored in the javascript client; it merely updates a counter when the web service returns.
Also, this problem occurs when using either the auto-generated client stubs from the ServiceReference or when using jQuery (change 'useJQuery' to true). I have also tried using jQuery with json2.js for the (de)serialisation with jQuery, but this made no apparent difference.
Here is the code for the test web service:
using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Collections.Generic;
using System.Web.Script.Services;
namespace WebServiceLeakTest
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class TestWebService : System.Web.Services.WebService
{
const int NUMBER_OF_RECORDS = 10;
[WebMethod]
public List<TestData> GetSomeData()
{
List<TestData> data = new List<TestData>(NUMBER_OF_RECORDS);
for (int i = 0; i < NUMBER_OF_RECORDS; i++)
{
TestData record = new TestData(
Guid.NewGuid().ToString(),
Guid.NewGuid().ToString(),
Properties.Resources.LorumIpsum);
data.Add(record);
}
return data;
}
}
}
As you can probably see, it doesn't do much special. It returns some dumb objects containing 3 string properties. Each of these dumb objects is populated with 2 GUIDs and about 70KB of arbitrary text. Therefore, each call to the web service is returning ~700KB.
If you try this out, you will need to increase the max JSON transfer length in your web.config file.
e.g. <jsonSerialization maxJsonLength="10000000" />
I have searched the web, MSDN etc but can not find anything useful or informative regarding this problem.
Has anyone else encountered this? Am I doing something wrong? Can anyone else reproduce this problem? Have I found a bad memory leak in IE9?
Regards,
James

The issue has to do with json parsing of the response I believe. I ran into a similar problem and isolated it to that.
Change you dataType to 'text' and you will see no more leaks. I think this has to do with jQuery using eval() for json parsing.
Anyway, I found a library json_parse.js which parses the json recursively. This worked for me on IE9. I didn't test it on any other browser only because the website I'm working on is only for IE.

This is AJAX leak problem caused by Jquery, I dont know which part of Jquery causing the leak though. It happened in IE7 and IE9 for me, I didnt bother to try with IE8 though
Proves:
$.ajax({
url : '/sometestservice',
dataType : "json",
success : function () {}
});
repeat this every second will eat up your RAM soon enough, now try this
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){};
xmlhttp.open("GET","/sometestservice",true);
xmlhttp.send();
So, I would say write your own ajax code.
Update:
It turn out the ajax code in jQuery didnt leak but itsJSON parsing does.
To reproduce repeat this to see the leak
var text = "{";
for (var i = 0; i < 1000; i++) {
text += "\"abc" + i + "\":10000000000000,";
}
text = text.substring(0, text.length -1);
text += "}";
( new Function( "return " + text) )();
Well I don't know if this would help but I fix the leak in my webapp by overriding JSON parsing in jQuery, using json_parse.js from https://github.com/douglascrockford/JSON-js.
This is a library from Douglas Crockford, note that json2 (which is pretty popular) is leaky cos it use eval()
That's all from me.

Related

AJAX code fails on Firefox and IE11 but ok on Chrome and Opera

I am learning AJAX and I have a problem with the following code.
This is a HTML page that, when downloaded to a browser, will allow the user to press a button to retrieve a 'clientes.xml' file from the server.
The code looks simple and seems to be in accordance with AJAX theory.
It actually works ok if I use a Chrome or an Opera browser.
The problem is that it always fails on Firefox (v45) and IE11.
By using the browser consoles, the following errors are reported:
Firefox: NS_ERROR_FAILURE error in the last line of the script: xhttp.send();
IE11: 'Permission denied' error on the same script line: xhttp.send();
By using Wireshark on the network, I can see that a HTTP GET message is always sent for the 'clientes.xml' file with Chrome and Opera but this never happens with Firefox or IE11.
I have already searched for a possible explanation for this but found none.
Does anyone know what might be the problem with Firefox and IE?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
var xhttp=new XMLHttpRequest();
function doStuff(response) {
// var papeis=response;
var clientes=response.getElementsByTagName("nome");
for (i = 0; i < clientes.length; i++) {
document.write("<p>");
document.write(clientes[i].childNodes[0].textContent);
}
}
function sendRequest() {
var xhttp=new XMLHttpRequest();
if (!xhttp) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
xhttp.onreadystatechange = function() {
console.log (xhttp.readyState);
if (xhttp.readyState!=4) {document.write("Not Yet Done: " + xhttp.readyState + "<br>" );}
else if(xhttp.readyState===4 && xhttp.status===200) {
doStuff(xhttp.responseXML);
}
}
xhttp.open('GET','clientes.xml', true);
xhttp.send();
}
</script>
</head>
<body>
<h3> AJAX </h3> <br>
<button onclick="sendRequest()">Click me</button>
</body>
</html>
I found where is the problem. The problem is in the javascript document.write() function which I used for testing purposes.
If I replace this function by console.log() in my sendRequest() function, Firefox will behave the same way as Chrome and Opera.

I need a clue about what code goes where for a simple AJAX query

I'm just blundering into AJAX, and I swear I'll actually learn my way around it real soon now, but all I need at the moment is to get the inner browser height, so I can ask the Google Maps Engine for a map of the appropriate height. (I'm actually making that request via the Google Maps plugin under Joomla. If I could somehow make that request on the client side, then I might not really have to mess with AJAX, but this would still be a good introductory exercize for me.)
I'm trying to grasp the basic AJAX setup by putting together a working minimal document incorporating code from the first answer at how to get screen width through php?. I realize that example is asking for a different attribute than I'll be asking for, but I'm just keeping the code as close to the original as possible.
I'm not totally clear on what code goes where, but apparently it is not this, at http://allbluesdance.com/testajax.php :
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Test Ajax</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
var width = $(window).width();
//This is ajax code which will send width to your php page in the screenWidth variable
$.ajax({
url: "http://allbluesdance.com/testajax.php", //this will be your php page
data : {screenwidth:width}
}).done(function() {
$(this).addClass("done");
});
</script>
(Yeah, it's running)
<!-- example.php code is here : -->
<?php
echo $width = $_REQUEST['screenwidth'];
?>
</body>
</html>
So unless I've made a dumb syntax error I could use a clue.
Thanks,
Drew
I think you need to specify how AJAX gets the data, either through GET or POST. I Have been using this snippet and it works for me.
// fire off the request
var request = $.ajax({
url: "/list/server.php",
type: "POST",
data: send_data
});
// callback handler that will be called on success
request.done(function (response){
// log a message to the console
console.log(response);
});

jQuery Mobile ajax request

I am trying to retrieve information from a javascript file in my jQuery mobile website. Ajax is enabled by default, yet when I try xmlHttpRequest.send(), the responseText is the source code for the page rather than a json structure. The initialize() function is run at pageinit, so my thinking is that the json it is retrieving should exist when called. Also, initialize() works fine on the non-mobile variant of the site so I think it has something to do with how JQM handles ajax requests. Thanks in advance for any assistance.
<!DOCTYPE html>
<html>
<head>
var xmlHttpRequest;
var json;
<script type="text/javascript">
function initialize()
{
xmlHttpRequest = (window.XMLHttpRequest) ? new XMLHttpRequest() :
new ActiveXObject("Msxml2.XMLHTTP");
if (xmlHttpRequest == null)
return;
xmlHttpRequest.open("GET", "pick.js", false);
xmlHttpRequest.send();
json = eval('('+ xmlHttpRequest.responseText +')');
}
</script>
......
</head>
<body>
<div data-role="page" id="map-page">
<script type="text/javascript">
$('#map-page').live('pageinit',function(){
initialize();
});
</script>
.....
</div>
</body>
</html>
Since you're using jQuery Mobile (and thusly, jQuery), you should consider using jQuery.ajax -- it handles all of the 'hard stuff' like creating XHR object for you.
For your situation your code would look like this:
function initialize() {
$.get("pick.js", function(data, status, jqXHR) {
//when the call succeeds, do something with the 'data' param
console.log(data);
}, "script");
}

AJAX not working with XAMPP or is it just impossible

I'm still relatively new to AJAX and am trying to figure out why my simple test is not working. From what I read AJAX will not work under one domain, and other words pop up like cross-site and remote server. Anyways my problem is is that I'm not sure if my code is wrong or simply what I'm trying to do is impossible. I created a simple ajax request to submit data when I click on the button. Here is the code for the first script.
<html>
<head>
<script type="text/javascript" >
function load(thediv, thefile) {
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById(thediv).innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open('GET', thefile, true);
xmlhttp.send();
}
</script>
</head>
<body>
<input type="submit" onclick="load('adiv', 'hello.php');">
<div id="adiv"></div>
</body>
</html>
Here is the code for the file hello.php
<?php
echo 'aaa';
?>
AJAX is just an http request done in the background. But yes, there are security restrictions that prevent you doing a normal ajax request to any arbitrary server.
What your code is missing is actually setting the URL that you're placing the request to. You've got hello.php as a parameter to your load() function, but you never actually USE it. So you're doing an AJAX request to... "nowhere".

Simple Ajax / page refresh

I'm experimenting on this code that I got from the net (I'm trying to make a simple chat but i do the message insertion manually in mysql database). It refreshes the page every 3 seconds and displays the new message in the page fetched from database. It works well in chrome and firefox but it doesn't in IE. What I have observed in IE is it will only display the new message every time I clear the cache or delete the cookies in the browser. Can anyone help me to devise a solution for this please...
Please see code:
<html>
<head>
<script type="text/javascript">
function showResult(str) {
document.getElementById("livesearch").innerHTML="";
if (str.length==0) {
document.getElementById("livesearch").innerHTML="";
document.getElementById("livesearch").style.border="0px";
return;
}
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
var msxmlhttp = new Array(
'Msxml2.XMLHTTP.5.0',
'Msxml2.XMLHTTP.4.0',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP',
'Msxml2.xmlHTTP
'Microsoft.XMLHTTP');
for (var i = 0; i <= msxmlhttp.length; i++) {
try {
xmlhttp = new ActiveXObject(msxmlhttp[i]);
}
catch (e) {
xmlhttp = null;
}
}
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("livesearch").innerHTML=xmlhttp.responseText;
document.getElementById("livesearch").style.border="1px solid #A5ACB2";
setTimeout("showResult('a')", 3000);
}
}
xmlhttp.open("GET","http://localhost/review/login/5/try.php",true);
xmlhttp.send();
}
</script>
</head>
<body onload="">
<script>
setTimeout("showResult('a')", 3000);</script>
<form>
<div id="livesearch"></div>
</form>
</body>
</html>
this is the code for try.php
<?php
require_once('config.php');
$link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
if(!$link)
{
die('Failed to connect to server: ' . mysql_error());
}
$db = mysql_select_db(DB_DATABASE);
if(!$db)
{
die("Unable to select database");
}
//Create query
$qry="SELECT * FROM message where message like '%".$_GET['a']."%'";
$result=mysql_query($qry);
if(mysql_num_rows($result) > 0)
{
while($row = mysql_fetch_assoc($result))
{
echo $row['message']."<br>";
//echo "<br> ".$member['message'];
}
}
?>
Please help...thanks...
Your best bet is to add the following headers to the top of your page that is to return the content you wish not to be cached
header('Last-Modified: Mon, 01 Jan 1970 05:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
This will allow you to control the cache on the server side rather then adding the "random" number hack at the end of the request.
It looks like a caching issue. You should try adding a random number to your URL. That will force IE to reload the page.
xmlhttp.open("GET","http://localhost/review/login/5/try.php?r=" + Math.random(),true);
I know that won't help you right now, at the first time, but I highly recommend you to use a JS library like jQuery. It makes ajax calls a lot simpler, and cross-browser. It will make your code clearer, and you will be able to focus on your logic instead of low level browser issues.
If you want to do AJAX stuff and have it work in multiple browsers I recommend taking a look at jQuery:
jQuery Home Page
It is reasonably easy to get started and it will make you much more productive.
In particular, take a look at jQuery.ajax():
jQuery.ajax()
You will probably initially experience the same problem with IE when using jQuery, but I think you can fix it by setting the cache parameter to false (as described on the page I link to above).

Resources