public static bool AppendStream(Stream streamFrom, Stream streamTo)
{
long size = streamTo.Length;
int bufferSize = 4096;
byte[] buf = new byte[bufferSize];
do
{
int bytesRead = streamFrom.Read(buf, 0, buf.Length);
if (bytesRead <= 0)
{
break;
}
streamTo.Write(buf, 0, bytesRead);
} while (true);
return streamTo.Length == size + streamFrom.Length;
}
Подскажите оптимальный размер буфера для Stream. Он может быть либо локальным файлом, либо получен через HttpWebRequest. Есть ли верхний порог на размер буфера?
Обычно все ставят что-нибудь типа 4096 или 8192 )
Это вроде бы значения по умолчанию где-то в .NET.
Можно попробовать поизмерять свое приложение с разными значениями. Но значительная разница (ухудшение скорости) скорее всего может быть только если слишком маленький (типа 1) или большой.
Однажды, при склеивании файлов, я случайно поставил размер буфера равный размеру самого файла. Это примерно 8 мегабайт. То есть, читался и писался весь файл за один вызов. Всё нормально склеилось и быстро работало.
Но что если стрим будет получен через HttpWebResponse.GetResponseStream()? Есть же ограничение на размер сетевого пакета (какое-то маленькое, не помню точно). Или обёртка его игнорирует?
Нет никакой связи между размером сетевого пакета и размером буфера в .Net-объекте Stream. Пакет сначала считывается в операционную систему, затем данные оттуда копируются в буфер в память процесса. В другую сторону в обратном порядке (разрезаясь на пакеты нужного размера).
А оптимальный размер я бы брал в зависимости от файловой системы. В линуксе это особенно наглядно на raid-маcсиве (stride size), например 65536KB chunk:
и вот 65-мегабайтным куском можно и читать, если памяти достаточно - это будет оптимально по скорости (на террабайтных файлах).
Верно, что размеры кластера раньше были 4 килобайта, или размер страницы в памяти процессоров на архитектуре Intel может быть 4 килобайта. Но какой смысл жаться и экономить? А страницы памяти и более крупные бывают, мегабайтные. https://wiki.osdev.org/Paging
Есть еще одна проблема. Если делать синхронизацию на каждой итерации, то при размере буфера 8192 форма начинает тормозить. Приходится либо увеличивать буфер (прямо-пропорционально скорости передачи), либо делать синхронизацию каждые N итераций.
Какой способ лучше?
Попробуй описать твою ситуацию так, чтобы было понятно другим людям. Форма это из Windows.Forms? При чём тут итерации? Как вообще вызывается код? Знаешь ли ты про класс BackgroundWorker ?
“Синхронизация” это сообщение прогресса для UI из другого потока?
Ну так это нормально, не надо 100 раз в секунду его дергать.
Тут не буфер менять надо, а просто каким-либо способом реже обновлять UI. “Раз в N” итераций/миллисекунд, debouncing и т.д.
То есть, вычислять delta time каждую итерацию это нормально?
Получается, программы, где есть настройки интервала обновления - так и работают? Тут, кстати, буфер по-дефолту UInt16.MaxValue стоит и ему норм.
Выходит, если он не успеет перекинуть 65536 байт за 100 миллисекунд, то GUI не обновится?
Офигеть Не знал, что у него есть исходники. Лет 7-10 назад очень хотелось поправить вывод в окне копирования
Кто, интересно, выложил? Я думал, они давно болт поклали. Последнее обновление, вроде, ажно до 2010 было