Какой размер буфера памяти лучше выделить для загрузки файла из Интернета?

Какой размер буфера памяти лучше выделить для загрузки файла из Интернета? Некоторые из образцов сказали, что это должно быть 1K. Ну, в общем, мне нужно знать, почему? А также какая разница, если мы загрузим небольшой .PNG или большой .AVI?

Stream remoteStream;
Stream localStream;
WebResponse response;

try
{
    response = request.EndGetResponse(result);

    if (response == null)
        return;

    remoteStream = response.GetResponseStream();

    var localFile = Path.Combine(FileManager.GetFolderContent(), TaskResult.ContentItem.FileName);
    localStream = File.Create(localFile);

    var buffer = new byte[1024];
    int bytesRead;

    do
    {
        bytesRead = remoteStream.Read(buffer, 0, buffer.Length);
        localStream.Write(buffer, 0, bytesRead);
        BytesProcessed += bytesRead;
    } while (bytesRead > 0);
}

6 ответов

Решение

Используйте по крайней мере 4 КБ. Это нормальный размер страницы для Windows (то есть степень детализации, при которой Windows сама управляет памятью), что означает, что распределителю памяти.Net не нужно разбивать страницу размером 4 КБ на выделения размером 1 КБ.

Конечно, использование блока размером 64 КБ будет быстрее, но только незначительно.

Чтобы проверить, стоит ли читать текстовый файл размером 1484 КБ, используя прогрессивные степени двойки (размеры 2,4,8,16...). Я распечатал в окне консоли количество миллисекунд, необходимое для чтения каждого из них. В прошлом 8192 году это не казалось большой разницей. Вот результаты на моей Windows 7 64-битной машине.

2^1 = 2 :264.0151
2^2 = 4 :193.011
2^3 = 8 :175.01
2^4 = 16 :153.0088
2^5 = 32 :139.0079
2^6 = 64 :134.0077
2^7 = 128 :132.0075
2^8 = 256 :130.0075
2^9 = 512 :133.0076
2^10 = 1024 :133.0076
2^11 = 2048 :90.0051
2^12 = 4096 :69.0039
2^13 = 8192 :60.0035
2^14 = 16384 :56.0032
2^15 = 32768 :53.003
2^16 = 65536 :53.003
2^17 = 131072 :52.003
2^18 = 262144 :53.003
2^19 = 524288 :54.0031
2^20 = 1048576 :55.0031
2^21 = 2097152 :54.0031
2^22 = 4194304 :54.0031
2^23 = 8388608 :54.003
2^24 = 16777216 :55.0032

У меня проблема с удаленным подключением к машине при использовании 64 Кб буфера при загрузке с iis.

Я решил проблему повышения буфера до 2М

2k, 4k или 8k - хороший выбор. Неважно, насколько велик размер страницы, изменение скорости будет действительно незначительным и непредсказуемым.

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

Во-вторых, массивы в C# могут быть образованы несмежной областью памяти! Массивы хранятся непрерывно в виртуальной памяти, но непрерывная виртуальная память не означает непрерывную физическую память.

В-третьих, структура данных массива в C# занимает на несколько байтов больше, чем сам контент (он хранит размер массива и другую информацию). Если вы выделите размер страницы в байтах, использование массива переключит страницу почти всегда!

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

Обычно массивы C# работают очень хорошо, но если вам действительно нужно точное распределение данных, вам нужно использовать закрепленные массивы или распределение Marshal, но это замедлит сборщик мусора.

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

Я бы сказал, что лучше использовать ваши массивы, не слишком задумываясь о размере страницы. Используйте 2К, 4К или 8К буферов.

Это также будет зависеть от оборудования и области применения. Я работаю над рабочими нагрузками, развернутыми в облаке, в мире серверов вы можете найти карты Ethernet 40G, и вы можете предположить, что MTU составляет 9000 байт. Кроме того, вы не хотите, чтобы ваша сетевая карта прерывала работу вашего процессора для каждого отдельного кадра. Таким образом, игнорируя промежуточные звенья в ядре Windows/Linux, вы должны выбрать в один или два раза больше:100 * 9000 ~~ 900 КБ, поэтому я обычно выбираю 512 КБ в качестве значения по умолчанию (пока я знаю, что это значение не превышает размер обычного ожидаемый размер загружаемого файла)

В некоторых случаях вы можете узнать (или узнать, или взломать в отладчике и, следовательно, узнать, хотя и не устойчивым к изменениям) размер буфера, используемого потоком (ами), в который вы пишете или читаете из, В этом случае это даст небольшое преимущество, если вы подберете этот размер или не достигнете его, если один буфер будет кратным другому.

В противном случае 4096, если у вас нет другой причины (например, желая небольшого буфера для быстрой обратной связи с пользовательским интерфейсом) по уже указанным причинам.

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