Internet Explorer 9 (IE9) протекает во время вызовов ajax / веб-службы? - PullRequest
1 голос
/ 08 ноября 2011

Я думаю, что, возможно, обнаружил довольно серьезную утечку памяти в Internet Explorer 9. Кажется, что при выполнении вызовов AJAX для веб-службы IE9 каждый раз теряет память.На самом деле, похоже, что она теряет больше памяти, чем размер соответствующей передачи.

Если вы наблюдаете за процессом IE9 в диспетчере задач, вы видите, что использование памяти увеличивается (и никогда не падает).В конечном итоге браузер использует ~ 1,5 ГБ памяти, после чего происходит сбой приложения.Очевидно, что это будет проблемой, если вы пытаетесь разработать веб-приложение AJAX, которое должно работать несколько дней подряд.

Это не происходит в IE8, Chrome или Firefox.Я также протестировал IE9 со всеми отключенными надстройками.

Ниже приведен код ASP.NET 2.0, который может воспроизвести проблему (вам понадобятся расширения MS ASP.NET AJAX, если вы хотите попробовать его):

<%@ 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>

Из кода вы заметите, что результаты, возвращаемые вызовом веб-службы, даже не сохраняются в клиенте javascript;он просто обновляет счетчик при возврате веб-службы.

Кроме того, эта проблема возникает при использовании автоматически сгенерированных заглушек клиента из ServiceReference или при использовании jQuery (измените «useJQuery» на true).Я также пытался использовать jQuery с json2.js для (де) сериализации с jQuery, но это не сделало очевидной разницы.

Вот код для тестового веб-сервиса:

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;
        }
    }
}

Как вы, вероятно, видите, это не делает ничего особенного.Возвращает некоторые тупые объекты, содержащие 3 строковых свойства.Каждый из этих тупых объектов заполнен двумя GUID и около 70 КБ произвольного текста.Поэтому каждый вызов веб-службы возвращает ~ 700 КБ.

Если вы попробуете это, вам нужно будет увеличить максимальную длину передачи JSON в файле web.config.

, например

Я искал в Интернете, MSDN и т. Д., Но не могу найти ничего полезного или информативного по этой проблеме.

Кто-нибудь еще сталкивался с этим?Я делаю что-то неправильно?Кто-нибудь еще может воспроизвести эту проблему?Нашел ли я плохую утечку памяти в IE9?

С уважением, Джеймс

Ответы [ 2 ]

1 голос
/ 03 октября 2012

Проблема связана с разбором json ответа, которому я верю.Я столкнулся с подобной проблемой и изолировал ее от этого.

Измените ваш dataType на 'text', и вы не увидите больше утечек.Я думаю, что это связано с jQuery, использующим eval () для анализа json.

В любом случае, я нашел библиотеку json_parse.js , которая рекурсивно анализирует json.Это работало для меня на IE9.Я не тестировал его ни в каком другом браузере, потому что веб-сайт, над которым я работаю, предназначен только для IE.

0 голосов
/ 18 ноября 2011

Это проблема утечки AJAX, вызванная Jquery, хотя я не знаю, какая часть Jquery вызывает утечку. Это произошло в IE7 и IE9 для меня, я не удосужился попробовать IE8, хотя

Доказывает:

$.ajax({
     url : '/sometestservice',
     dataType : "json",
     success : function () {}
});

повторяйте это каждую секунду достаточно скоро съест вашу оперативную память, теперь попробуйте это

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();

Итак, я бы сказал, написать свой собственный код AJAX.


Обновление: Оказалось, что ajax-код в jQuery не просочился, но его разбор JSON делает.

Для воспроизведения повторите это, чтобы увидеть утечку

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) )();

Ну, я не знаю, поможет ли это, но я устраню утечку в моем веб-приложении, переопределив анализ JSON в jQuery, используя json_parse.js из https://github.com/douglascrockford/JSON-js. Это библиотека от Дугласа Крокфорда, обратите внимание, что json2 (который довольно популярен) является утечкой, потому что он использует eval ()

Это все от меня.

...