WCF BufferManager ReturnBuffer против Clear

Я использую BufferManager в моей службе WCF. Я создал свой собственный класс, чтобы обернуть вокруг BufferManager, который реализует IDisposable. Прямо сейчас мой метод Dispose выглядит так:

public void Dispose()
    {
        this.bufferManager.Clear();
    }

Мой вопрос: выполняет ли это то же самое, что и вызов ReturnBuffer для всех буферов, которые были приняты менеджером?

Просто для справки: я использую BufferManager в следующем методе:

public byte[] ReadAllBufferedBytes(string filePath)
    {
        using (var fileStream =
            new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = this.bufferManager.TakeBuffer((int)fileStream.Length);

            fileStream.Read(buffer, 0, buffer.Length);

            return buffer;
        }
    }

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

Хост-сервер имеет 3 ГБ памяти. Служба находится в режиме InstanceContextMode.Single, поэтому изображения обрабатываются по одному. Изображения принимаются в виде байтовых массивов - самые большие могут составлять 100 МБ, но обычно они гораздо меньше - преобразуются, а затем возвращаются в виде байтового массива. Многое заканчивается в куче больших объектов, а размеры изображений довольно сильно различаются.

Мне интересно, если проблема в фрагментации кучи.

Когда каждая страница документа конвертируется, она добавляется во временный файл на диске. После преобразования я считываю весь преобразованный файл с диска в байтовый массив и возвращаю его клиенту.

Стандартный метод File.ReadAllBytes создает новый байтовый массив при чтении из файла, который неизбежно заканчивается в LOH из-за размеров изображения, с которыми я работаю (полагаю, именно это и происходит). Я создал метод ReadAllBufferedBytes, чтобы сделать то же самое, но для буферизации массива байтов и позволить BufferManager возвращать буфер, когда он удаляется.

Другой вопрос: нужно ли мне все это делать?

1 ответ

BufferManager обычно используется в сценариях, где вы должны предотвратить давление ГХ - там, где много мелких byte[] назначения, как при получении или отправке данных на очень низком уровне (например, сокеты). Акцент здесь делается на многое, в противном случае сборщик мусора должен уметь справляться с распределением памяти.

Чтобы предотвратить загрузку всего преобразованного файла документа в память, вы должны использовать FileStream напрямую (без чтения всего содержимого в память - байт []) в сочетании с потоковым (ответным) TransferMode, если это возможно.

Другие вопросы по тегам