Слишком много физической памяти для приложения asp.net? - PullRequest
2 голосов
/ 10 ноября 2008

Мои огромные 32-битные веб-сервисы Приложение доступа к данным на основе LLBLGen работает в одиночку на выделенной 64-битной машине. Потребление физической памяти постоянно растет примерно до 2 ГБ, когда процесс освобождает почти все выделенное пространство (до 1,5 ГБ) и продолжает расти с этого момента. Наблюдаемого увеличения значений Page Input или других параметров использования файла подкачки не наблюдается, поэтому похоже, что память освобождается, а не выгружается в файл подкачки. Я думаю, что это за профиль? На самом деле ничто не может помешать процессу захватить всю память, которую он может, с другой стороны, существуют недопустимые внутренние ошибки http при освобождении памяти - вероятно, очистка блокирует полезную работу. Что было бы хорошей стратегией, чтобы сделать очистку менее навязчивой, учитывая, что вышеупомянутое является приемлемым поведением в первую очередь.

Ответы [ 8 ]

2 голосов
/ 10 ноября 2008

Похоже, что у вас утечка памяти, процесс продолжает утекать память до тех пор, пока не завершится с состоянием нехватки памяти, а затем автоматически перезапустится сервером.

1,5 ГБ - это максимальный объем памяти, который 32-разрядный процесс может выделить до исчерпания адресного пространства.

Что искать:

  • Вы занимаетесь кешированием? когда элементы удаляются из кэша?
  • Есть ли данные, которые время от времени добавляются в коллекцию, но никогда не удаляются?
  • Вы вызываете Dispose для каждого объекта, который реализует IDisposable?
  • Имеете ли вы доступ к какому-либо неуправляемому коду (объекты COM или с помощью DllImport) или выделяете неуправляемую память (например, с помощью класса Marshal)? все, что там находится, никогда не освобождается сборщиком мусора, вы должны освободить его самостоятельно.
  • Используете ли вы сторонние библиотеки или какой-либо код сторонних разработчиков? у него тоже могут быть проблемы из списка.
1 голос
/ 10 ноября 2008

Я согласен с первой частью ответа Эдга, но там, где он говорит:

"Путем установки объектов в нуль, когда они мертвы, вы можете призвать GC повторно использовать память, потребляемую этими объекты, ограничивающие рост потребление памяти. "

неверно. Вам никогда не нужно устанавливать объект в null, поскольку GC в конечном итоге будет собирать ваш объект после того, как он выйдет из области видимости.

Это обсуждалось в этом ответе на SO: Установка объектов в Null / Nothing после использования в .NET

1 голос
/ 10 ноября 2008

Возможно ли, что вы не утилизируете различные одноразовые предметы (в частности, связанные с БД). Это оставит их вокруг, потенциально связывая большие объемы неуправляемых ресурсов, пока GC не запустится и не будут вызваны их финализаторы.

Было бы целесообразно запустить perfmon против вашего процесса и посмотреть, будет ли устойчивый рост в некоторых критических ресурсах, таких как дескрипторы, или если ваш поставщик БД выставляет счетчики производительности, затем соединения или открытые наборы результатов.

0 голосов
/ 10 ноября 2008

Моим первым предположением будет утечка памяти. Мое второе предположение было бы, что это нормальное поведение - GC не будет запущен, пока у вас не будет значительного давления памяти. Единственный способ убедиться в этом - использовать комбинацию профилировщика и таких вещей, как PerfMon. Некоторые сайты:

Кроме того, я хотел бы убедиться, что вы не работаете в режиме отладки (как уже упоминалось).

Что касается ошибок HTTP - при условии, что вы работаете в режиме GC сервера, он пытается сделать все возможное, чтобы не блокировать запросы. Было бы интересно узнать, что это за ошибки HTTP - это ненормальное поведение из того, что я видел в прошлом, и может указывать на еще одну причину вашей проблемы.

0 голосов
/ 10 ноября 2008

У нас были похожие ситуации, и мы изменили все наши соединения с базой данных, чтобы использовать подход try / catch / finally. Try был использован для выполнения кода, перехвата для сбора ошибок и, наконец, для закрытия всех переменных и соединений с базой данных.

internal BECollection<ReportEntity> GetSomeReport()
    {
        Database db = DatabaseFactory.CreateDatabase();
        BECollection<ReportEntity> _ind = new BECollection<ReportEntity>();
        System.Data.Common.DbCommand dbc = db.GetStoredProcCommand("storedprocedure");

        try
        {
            SqlDataReader reader = (SqlDataReader)db.ExecuteReader(dbc);
            while (reader.Read())
            {
                //populate entity
            }
        }
        catch (Exception ex)
        {
            Logging.LogMe(ex.Message.ToString(), "Error on SomeLayer/SomeReport", 1, 1);
            return null;
        }
        finally
        {
            dbc.Connection.Close();
            _ind = null;
        }
        return _ind;
    }
0 голосов
/ 10 ноября 2008

Убедитесь, что вы не запускаете отладочную сборку вашего проекта. Есть особенность *, что когда у вас есть отладочная сборка, если вы создаете экземпляр любого объекта, который содержит определение для события, даже если вы не вызываете событие, он будет неопределенно долго удерживать только небольшой фрагмент памяти. Со временем эти небольшие кусочки памяти будут поглощать ваш пул памяти, пока в конечном итоге он не перезапустит веб-процесс и не запустится снова.

* Я называю это функцией (а не ошибкой), потому что она существует с самого начала .Net 2 (отсутствует в .Net 1.1), и не было патча для ее исправления. Утечка памяти должна быть связана с некоторыми функциями, необходимыми при отладке.

0 голосов
/ 10 ноября 2008

Не используйте Arraylists (сборщик мусора не работает с ними), вместо этого используйте общие списки

Другая распространенная ошибка - иметь в web.config Debug = true, это занимает много памяти, измените опцию на «false».

Другая вещь, которую нужно сделать, это использовать CLRProfiler, чтобы отследить проблему.

Удачи, Pedro

0 голосов
/ 10 ноября 2008

Сборщик мусора не освобождает память автоматически при освобождении объектов, он удерживает эту память, чтобы помочь минимизировать расходы на будущие mallocs.

При возникновении проблемы с нехваткой памяти эта память будет возвращена ОС, и вы увидите больше доступной памяти при просмотре диспетчера задач. Обычно это происходит с отметкой 2 ГБ или 3 ГБ, если вы используете соответствующий переключатель .

<contentious>

Установив нулевые объекты, когда они мертвы, вы можете побудить GC повторно использовать память, потребляемую этими объектами, что ограничивает растущее потребление памяти.

Но какие объекты вы должны установить на ноль? Большие объекты, большие коллекции, часто создаваемые объекты.

</contentious>

РЕДАКТИРОВАТЬ : Есть доказательства, подтверждающие значение установки объектов на ноль. Подробнее см. this . Конечно, не нужно для установки объектов на ноль, смысл в том, помогает ли это каким-либо образом управлению памятью?

РЕДАКТИРОВАТЬ : нам нужен недавний тест, если такая вещь существует, а не продолжать высказывать свое мнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...