Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileStream constructor and default buffer size

Tags:

c#

.net

We have a logging class written in C# using .NET 4. I want to add a constructor argument which will optionally set the FileOptions.WriteThrough flag when constructing a FileStream. As this is widely used library code I want to change as little as possible.

Existing FileStream constructor call:

_stream = new FileStream(_filePath, FileMode.Append, FileAccess.Write, FileShare.Read);

The problem:

To our constructor I have added an optional bool argument named writeDirectToDisk. I thought I'd then be able to do something like this:

var fileOptions = writeDirectToDisk ? FileOptions.WriteThrough : FileOptions.None;
_stream = new FileStream(_filePath, FileMode.Append, FileAccess.Write, FileShare.Read, fileOptions);

but no, there's no such overload! Unless I'm missing something the only overloads available for FileStream's constructor which accept a FileOptions argument also require a buffer size argument!

What I've tried:

I've tried setting buffer size to zero hoping that would use the default buffer size but no it throws an exception.

I've searched for and can't find some static property or constant in the framework which specifies what the default buffer size is.

My question:

I'm not at this stage particularly bothered about how many bytes the default buffer size is. I just want to know how I can add the FileOptions argument to the constructor with as little code impact as possible?

I'm wondering if there is some constant or static var which I've missed that I could use as the buffer size argument or if there's an overload I've missed or indeed if there's some smarter way to do this. I'm also wondering if the buffer size is irrelevant when FileOptions.WriteThrough is specified in which case I could do this:

            if (writeDirectToDisk)
            {
                _stream = new FileStream(_filePath, FileMode.Append, FileAccess.Write, FileShare.Read, 1, FileOptions.WriteThrough); // 1 is the smallest value allowed, it will actually be 8 bytes
            }
            else
            {
                _stream = new FileStream(_filePath, FileMode.Append, FileAccess.Write, FileShare.Read);
            }

but I'd rather not unless there's really no more elegant way.

like image 794
Stephen Kennedy Avatar asked Mar 20 '12 16:03

Stephen Kennedy


2 Answers

The default buffer size can be seen in .Net's source code, here.

WriteThrough is not supported in .Net. You can use unmanaged Win API calls is you really want that functionality. I just spent a day experimenting with it, and there are no advantages to using it. This was not true 10+ years ago, where the caching had a noticeable effect on speed.

Out of interest, someone kindly wrote the whole library for doing the API calls, available here.

like image 60
IamIC Avatar answered Oct 28 '22 10:10

IamIC


You could use your own factory method to construct the FileStream.

Other than that, you could hardwire the buffer size discovered using Reflector (0x1000).

like image 26
Joe Avatar answered Oct 28 '22 10:10

Joe