Оптимизация использования памяти

public static byte[] Compress(byte[] data)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress))
        {
            ds.Write(data, 0, data.Length);
            ds.Flush();
        }
        return ms.ToArray();
    }
}

Будет ли закрыт поток памяти в функции выше? Или лучше назначить поток памяти массиву и вместо этого вернуть массив?

public static byte[] Compress(byte[] data)
{
    byte[] compressedData;
    using (MemoryStream ms = new MemoryStream())
    {
        using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress))
        {
            ds.Write(data, 0, data.Length);
            ds.Flush();                   
        }
        compressedData= ms.ToArray();
    }
    return compressedData;
}

Какой из кодов лучше оптимизирует использование памяти?


person xaria    schedule 05.04.2012    source источник
comment
Чувак, это КОД, а не коды! Блин! english.stackexchange.com/questions/20455/   -  person    schedule 05.04.2012
comment
Вариант 1 чище и лучше (на одну ссылочную переменную меньше), как указывают ответы. Кроме того, вам не нужно выполнять промывку с помощью ds.Flush (); 'using' закроет поток (и, конечно, закроет сброс перед закрытием)   -  person Om Deshmane    schedule 05.04.2012


Ответы (4)


Очень похожие результаты и не стоит усилий.

Чтобы ответить на ваш вопрос, поток памяти закрывается, потому что он выходит из области видимости и находится в блоке использования, что означает, что Dispose будет вызываться ala шаблоном IDispose. В стороне, я лично предпочитаю ваш второй пример, так как его легче остановить в отладчике, чтобы проверить содержимое compressedData. Но на самом деле это не стоит усилий по рефакторингу во имя производительности.

В другом месте можно добиться большего.

Пример кода здесь из MemoryStream.toArray выглядит так

byte[] numArray = new byte[this._length - this._origin];
Buffer.InternalBlockCopy(this._buffer, this._origin, numArray, 0, this._length - this._origin);
return numArray;

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

Внутренний поток памяти - это этот код

protected override void Dispose(bool disposing)
{
    try
    {
        if (disposing)
        {
            this._isOpen = false;
            this._writable = false;
            this._expandable = false;
        }
    }
    finally
    {
        base.Dispose(disposing); // ultimately this will dispose of the stream 
    }
}
person krystan honour    schedule 05.04.2012

Я думаю, вы можете пойти по пути чрезмерной оптимизации, но, увы ...

Посмотрите на код IL. Скорее всего, это будет тот же код или очень похожий. Это лучшая микро-оптимизация.

Лично я бы выбрал вариант 1 для удобства чтения и меньшего количества кода.

person Michael Rice    schedule 05.04.2012

MemoryStream будет закрыт в обоих случаях. Таким образом, код работает идентично, поэтому первая версия лучше (так как она короче и понятнее). Использование памяти также идентично, за исключением дополнительной дополнительной ссылочной переменной compressedData во втором случае, которая будет уничтожена после выхода из метода.

person Petr Abdulin    schedule 05.04.2012

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

И, конечно же, нет ничего и для Flush, поскольку Flush предназначен для записи во внутренний массив перед записью в базовый поток ... MS некуда больше писать, кроме как во внутренний буфер 'stream', поэтому он всегда сбрасывается.

Ссылки, такие как Albahari (C # x.x in a Nutshell), также повторяют, что потоки MemoryStream не нуждаются в удалении.

person Nicholas Petersen    schedule 05.04.2012