FileStream.Length and what I learned
I’m writing a tool that has, at the core, only one task. Upload file or files to the Azure blob as fast and as efficiently as possible. Nothing special overall. The devil is in details. As usual.
The upload is obviously done in slices into blocks. At one part I’m looping though the slices and processing (uploading, progress reporting, check sums, etc.). Part of that loop is also reading FileStream
’s property Length
. As I was pushing the performance and also testing it on remote file systems (SMB/CIFS) sometimes the program ended with IOException
saying The semaphore timeout period has expired.
. Because I wrote my own semaphore I was first confused, looking for a clue in my implementation. But when I checked the call stack carefully I saw the exception originating from Length
’s getter. Quick look at implementation and it was clear. Every call to this property does P/Invoke call to Win32. And it makes sense. The size of file might change during, so it cannot cache it. And I was reading it a lot during the loop.
Luckily for me I knew the size cannot change as I’m having exclusive lock on the file. I extracted it into local variable and tested. Not only it worked slightly faster (at this stage of coding every small speedup matters for me), but it also finished without an exception.
Although the FileStream.Length
property behavior is completely clear I haven’t thought about it until I experienced it. I love when something that obvious connects dots in my head.