WCF - Проблемы с памятью при десериализации больших потоковых объектов - PullRequest
2 голосов
/ 08 июля 2010

Вот моя ситуация - у меня есть простая объектная модель.В корне есть объект отчета.Отчеты имеют массив документов.Каждый документ имеет массив глав и страниц.Каждый из этих объектов имеет 4 или 5 свойств (примитивы - строки и целые числа).Это выглядит примерно так:

  • Отчет
    • Список <Документ>
      • Список <Глава>
      • Список <Страница>

Достаточно просто, верно?

Вот моя проблема.После завершения длительного процесса у меня есть объект отчета, который обычно имеет около 5000 объектов Document.Каждый документ содержит примерно 200 объектов главы и 200 объектов страницы.

Другими словами, объект Report имеет довольно большой объем памяти.5000 документов, 1 000 000 глав и 1 000 000 страниц.Если я сериализую объект в поток памяти, он может достигать 80 МБ.

Проблема в том, что мне нужно переместить этот объект по проводам (да, это ОБЯЗАТЕЛЬНО).

Вот где мне нужна помощь!

Моей первой попыткой было просто попытаться переместить весь объект по проводу, используя стандартный сервис WCF с объектной моделью, украшеннойАтрибуты DataContract / DataMember.Учитывая количество объектов в графе и общий размер сериализованного объекта (поскольку WCF создает XML), это невозможно.Даже установка maxReceivedMessageSize и maxItemsInObjectGraph в их максимально возможные значения не позволяет выполнить работу.Кроме того, это буферизованный запрос, и он не выглядит хорошей идеей.

Моя вторая попытка состояла в создании WCF StreamedRequest с использованием экземпляра System.ServiceModel.Channels.Message .Это, кажется, работает, чтобы получить большой объект Report через провод без каких-либо проблемЗапрос передается в потоковом режиме, поэтому транспорт не является проблемой.Проблема, однако, заключается в том, что мне нужно десериализовать объект, когда его получает служба WCF.Я пробовал пару разных подходов (все на основе потоков) с постоянной проблемой.Десериализация объекта поднимает объем памяти W3WP с 115 000 КБ (обычно) до более чем 2,2 ГБ!И это десериализация только 1 объекта отчета.Плюс десериализация очень медленная!

Я не знаю, происходит ли скачок памяти в 2,2 ГБ из-за настроек WCF для такого свойства, как maxReceivedMessageSize , или если в процессе десериализации есть какая-то утечка(В настоящее время я использую DataContractSerializer).Что бы это ни было, я застрял.

Итак, у вас это есть - крупный объект должен пройти через провод, а затем быть десериализованным, не занимая вечность и не занимая всю доступную память.

У кого-нибудь есть предложения?Я полностью открыт практически для любого решения;Мне все равно, насколько это необычно или креативно.Единственные ограничения:

  1. Требуется размещение в IIS
  2. Требуется разумная эффективность при использовании памяти.

Спасибо всем!

1 Ответ

0 голосов
/ 23 июля 2010

Я бы разбил его на несколько звонков.Первый вызов - это запрос на создание отчета, его сохранение и возвращение объекта, который идентифицирует отчет.Последующие вызовы должны запросить разумную часть отчета путем передачи объекта отчета другому методу.Возможно, запросите диапазон документов.

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

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