views:

218

answers:

4

Hi, I'm working on a system that requires high file I/O performance (with C#). Basically, I'm filling up large files (~100MB) from the start of the file until the end of the file. Every ~5 seconds I'm adding ~5MB to the file (sequentially from the start of the file), on every bulk I'm flushing the stream. Every few minutes I need to update a structure which I write at the end of the file (some kind of metadata).

When flushing each one of the bulks I have no performance issue. However, when updating the metadata at the end of the file I get really low performance. My guess is that when creating the file (which also should be done extra fast), the file doesn't really allocates the entire 100MB on the disk and when I flush the metadata it must allocates all space until the end of file.

Guys/Girls, any Idea how I can overcome this problem?

Thanks a lot!

From comment:

In general speaking the code is as follows, first the file is opened:

m_Stream = new FileStream(filename, 
         FileMode.CreateNew, 
         FileAccess.Write, 
         FileShare.Write, 8192, false); 
m_Stream.SetLength(100*1024*1024);

Every few seconds I'm writing ~5MB.

m_Stream.Seek(m_LastPosition, SeekOrigin.Begin); 
m_Stream.Write(buffer, 0, buffer.Length); 
m_Stream.Flush(); 
m_LastPosition += buffer.Length;  // HH: guessed the +=
m_Stream.Seek(m_MetaDataSize, SeekOrigin.End); 
m_Stream.Write(metadata, 0, metadata.Length); 
m_Stream.Flush();  // Takes too long on the first time(~1 sec).
A: 

Have you tried the AppendAllText method?

Darin Dimitrov
Thanks a lot for the quick replies.I was afraid to get these answers :-)Moving the metadata to any other place other than the end of file is problematic but i looks like I don't have any other option.Thanks a lot people
Why are you calling Flush()? What do you expect to gain by doing it?
Stewart
A: 

Your question isn't totally clear, but my guess is you create a file, write 5MB, then seek to 100MB and write the metadata, then seek back to 5MB and write another 5MB and so on.

If that is the case, this is a filesystem problem. When you extend the file, NTFS has to fill the gap in with something. As you say, the file is not allocated until you write to it. The first time you write the metadata the file is only 5MB long, so when you write the metadata NTFS has to allocate and write out 95MB of zeros before it writes the metadata. Upsettingly I think it also does this synchronously, so you don't even win using overlapped IO.

Stewart
Wrong, the FS doesn't have to 'write' anything in between.
Henk Holterman
Are you sure about that? NTFS definitely supports sparse files, but it doesn't use them by default and you need special OS privileges to enable them. This would suggest that the 95MB of unused file actually does need to get allocated and zeroed.
Stewart
A: 

How about using the BufferedStream?

http://msdn.microsoft.com/en-us/library/system.io.bufferedstream(v=VS.100).aspx

code4life
+1  A: 

As suggested above would it not make sense (assuming you must have the meta data at the end of the file) write that first.

That would do 2 things (assuming a non sparse file)... 1. allocate the total space for the entire file 2. make any following write operations a little faster as the space is ready and waiting.

Can you not do this asyncronously? At least the application can then move on to other things.

Wardy