Здравствуйте, tapatoon, Вы писали:
T>Здравствуйте, Sinclair, Вы писали:
S>>Здравствуйте, tapatoon, Вы писали: T>>>Я ж написал — при оптимальном размере буфера в 4КБ разницы нет S>>Это не "оптимальный" размер буфера, а размер по умолчанию. Вот мне и интересно, что вы такое там намерили, что переделка его "на винапи" ускорила работу в 100 раз, или хотя бы в полтора.
T>В коде используются внутренние либы, если оставить суть, получится то, что я уже приводил. Но раз Вы настаиваете, приведу ешё раз: T>
T>using (FileStream file = new FileStream(filePath...)) // или Kernel32.CreateFile
T>{
T> long bytesWritten = 0;
T> do
T> {
T> var data = getData();
T> file.Write(data, 0, data.Length); // или Kernel32.WriteFile
T> bytesWritten += data.Length;
T> }
T> while (continueWrite(bytesWritten));
T>}
T>
T>Когда я переписал на винапи, я накапливал по 4Кб и только тогда вызывал WriteFile: https://github.com/microsoft/referencesource/blob/master/mscorlib/system/io/filestream.cs#L398
Это как раз то место, где FileStream накапливает по 4кб, и только тогда вызывает WriteFile. T>Потом Вы меня попросили код. Тут до меня дошло, что в FileStream передаются небольшие порции, а так не честно. Сделал размер буферов одинаковыми
Что значит "сделал размеры буферов одинаковыми"? Вы сконструировали FileStream с нестандартным размером буфера?
T>2) FileStream + запись небольшими порциями — в разы (до 10 если отдавать по 1 байту) T>3) FileStream + запись в него по 4Кб — одинаковая скорость
Очень, очень странно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, tapatoon, Вы писали:
T>Итог, разница WriteFile с переданным буфером в 4Кб и T>1) FileStream + BinaryWriter + запись небольшими порциями — сотни раз T>2) FileStream + запись небольшими порциями — в разы (до 10 если отдавать по 1 байту)
BinaryWriter в методе Write принимающий массив байтов просто делегирует вызов в основной поток (в данном случае FileStream.Write), т.е. получается что эта разница на порядки между 1) и 2) только за счёт косвенного вызова FileStream.Write? Выглядит фантастикой.
T>3) FileStream + запись в него по 4Кб — одинаковая скорость
Так то разница между 2) и 3), при записи небольшими порциями (менее внутреннего буфера FileStream'а, дефолтный размер которого 4k), конечно есть — FileStream сначала наполняет свой внутренний буфер (т.е. происходит копирование из переданного буфера во внутренний; при записи одного байта в .NET Fw создавался временный массив байтов размером 1b (при записи 1gb — "гигабайт" временных объектов) который уже передавался во Write(byte[]...), в .NET Core оптимизировали — сразу пишут байт во внутренний буфер). При записи массива байт размером не менее внутреннего буфера — запись сразу уходит в нейтив.
Наблюдаемый мной итог — при записи буферов одинакового размера используя FileStream и WriteFile (Win32) разницы между ними практически нет (что подтверждает 3) ), а при записи огромного количества маленьких буферов (1b в пределе) WriteFile может быть и проиграет (он тоже имеет внутренний буфер, если специально не указано при открытии файла) за счёт стоимости системного вызова.
Здравствуйте, pilgrim_, Вы писали:
_>Здравствуйте, Serginio1, Вы писали:
S>>Вообще то для буферизации стрима есть BufferedStream
S>> Ну и оптимальным у народа получалось порядка 256Кб
_>FileStream уже имеет встроенную поддержку буферизации, ему этот класс не нужен.
Здравствуйте, Serginio1, Вы писали:
_>>FileStream уже имеет встроенную поддержку буферизации, ему этот класс не нужен.
S> Я знаю. Он использует BinaryWriter для буферизации стрима.
BinaryWriter не занимается буферизацией, FileStream этим занимается сам.
Здравствуйте, tapatoon, Вы писали: T>Пишу в файл данные несколько гигабайт. Пишу небольшими порциями по нескольку байт
Самый суровый и былинный способ записи который знаю — создать файл, указать ему размер с запасом,
мапнуть в память и дальше писать в кусок памяти,
при окончании отмапнуть и поменять размер файла на актуальный.
Быстрее только не писать вообще.
А вообще самый главный косяк тут — возврат микробуферов из getdata вместо фунции writeData(Stream)
Здравствуйте, Sinclair, Вы писали:
S>Что значит "сделал размеры буферов одинаковыми"? Вы сконструировали FileStream с нестандартным размером буфера?
Размер буфера, передаваемого во Write(File). var data = getData();
getData отдаёт по 4КБ