My application needs to open a lot of small files, say 1440 files each containing data of 1 minute to read all the data of a certain day. Each file is only a couple of kB big. This is for a GUI application, so I want the user (== me!) to not have to wait too long.
It turns out that opening the files is rather slow. After researching, most time is wasted in creating a FileStream (OpenStream = new FileStream) for each file. Example code :
// stream en reader aanmaken
FileStream OpenStream;
BinaryReader bReader;
foreach (string file in files)
{
// bestaat de file? dan inlezen en opslaan
if (System.IO.File.Exists(file))
{
long Start = sw.ElapsedMilliseconds;
// file read only openen, anders kan de applicatie crashen
OpenStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Tijden.Add(sw.ElapsedMilliseconds - Start);
bReader = new BinaryReader(OpenStream);
// alles in één keer inlezen, werkt goed en snel
// -bijhouden of appenden nog wel mogelijk is, zonodig niet meer appenden
blAppend &= Bestanden.Add(file, bReader.ReadBytes((int)OpenStream.Length), blAppend);
// file sluiten
bReader.Close();
}
}
Using the stopwatch timer, I see that most (> 80%) of the time is spent on creating the FileStream for each file. Creating the BinaryReader and actually reading the file (Bestanden.add) takes almost no time.
I'm baffled about this and cannot find a way to speed it up. What can I do to speed up the creation of the FileStream?
update to the question:
The FileStream object is given the default buffer size of 8192 bytes. FileStream assumes that it has exclusive control over the handle. Reading, writing, or seeking while a FileStream is also holding a handle could result in data corruption.
Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.
The FileStream is a class used for reading and writing files in C#. It is part of the System.IO namespace. To manipulate files using FileStream, you need to create an object of FileStream class. This object has four parameters; the Name of the File, FileMode, FileAccess, and FileShare.
Remarks. Use the FileStream class to read from, write to, open, and close files on a file system, and to manipulate other file-related operating system handles, including pipes, standard input, and standard output.
As you have mentioned in the comment to the question FileStream
reads first 4K to buffer by creating the object. You can change the size of this buffer to reflect better size of your data. (Decrease if your files are smaller than the buffer, for example). If you read file sequentially, you can give OS the hint about this through FileOptions
. In addition, you can avoid BinaryReader
, because you read files entirely.
// stream en reader aanmaken
FileStream OpenStream;
foreach (string file in files)
{
// bestaat de file? dan inlezen en opslaan
if (System.IO.File.Exists(file))
{
long Start = sw.ElapsedMilliseconds;
// file read only openen, anders kan de applicatie crashen
OpenStream = new FileStream(
file,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite,
bufferSize: 2048, //2K for example
options: FileOptions.SequentialScan);
Tijden.Add(sw.ElapsedMilliseconds - Start);
var bufferLenght = (int)OpenStream.Length;
var buffer = new byte[bufferLenght];
OpenStream.Read(buffer, 0, bufferLenght);
// alles in één keer inlezen, werkt goed en snel
// -bijhouden of appenden nog wel mogelijk is, zonodig niet meer appenden
blAppend &= Bestanden.Add(file, buffer, blAppend);
}
}
I do not know type of Bestanden
object. But if this object has methods for reading from array you can also reuse buffer for files.
//the buffer should be bigger than the biggest file to read
var bufferLenght = 8192;
var buffer = new byte[bufferLenght];
foreach (string file in files)
{
//skip
...
var fileLenght = (int)OpenStream.Length;
OpenStream.Read(buffer, 0, fileLenght);
blAppend &= Bestanden.Add(file, /*read bytes from buffer */, blAppend);
I hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With