开发者

Why is File.Exists() much slower when the file does not exist?

Seems to me that File.Exists() is much slower when the file does not exist or the user doesn't have access than when the file does exist.

is this true?

This doesn't make开发者_如何学运维 sense to me.


File.Exists is trapping exceptions. The overhead of raising and capturing an exception may contribute to poor performance.

File.Exists works like this:

To check to see if the file exists, it tries to open the file... if an exception is thrown the file doesn't exist.

That process is slower than opening a file and no exception is thrown (which is when the file exists).


File.Exists also instantiates CLR permissioning before checking the file exists for the file. An alternative (though I haven't tried for performance) is PathFileExists if you're doing a lot of checks:

[DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
private extern static bool PathFileExists(StringBuilder path);

void Exists()
{
    // A StringBuilder is required for interops calls that use strings
    StringBuilder builder = new StringBuilder();
    builder.Append(@"C:\test.txt");
    bool exists = PathFileExists(builder);
}


Generally when you search a bunch of stuff for something, you can't be sure about their lack of existence unless you have searched all possible places it could have been. When searching for something (in most kinds of collections) the worst case is when the item doesn't exist in the collection.

I have not benchmarked File.Exists in particular but I highly doubt that there's a really noticeable difference in those cases unless you're doing it thousands of times. How did you reach to this conclusion?


I ran the following test, and on my PC at least, the times are about the same:

  static void TestExists()
     {
     Stopwatch sw = Stopwatch.StartNew();

     for ( int i = 0; i < 1000; i++ )
        {
        if ( !File.Exists( @"c:\tmp\tmp" + i.ToString() + ".tmp" ) )
           Console.WriteLine( "File does not exist" );
        }
     Console.WriteLine( "Total for exists: " + sw.Elapsed );

     sw = Stopwatch.StartNew();
     for ( int i = 0; i < 1000; i++ )
        {
        if ( File.Exists( @"c:\tmp\tmp_" + i.ToString() + ".tmp" ) )
           Console.WriteLine( "File exists" );
        }
     Console.WriteLine( "Total for not exists: " + sw.Elapsed );
     }

The results were along the lines of the following (each run is slightly different but about the same):

Total for exists: 00:00:00.0717181
Total for not exists: 00:00:00.0824266

But across a network (on the LAN to a server one hop away), I found the test to be quite a bit slower when the files actually existed. I sniffed it and there was only one SMB packet each direction.

Total for exists: 00:00:02.4028708
Total for not exists: 00:00:00.6910531


File and all of its methods typically work with windows file handles.

If you do a lot of checks, you should use :

FileInfo fiInfo = new FileInfo(@"c:\donotexists");
if (fiInfo.Exists)
    return true;

Rather than working internally with file handles, it looks at file attributes and is a lot more faster. Besides, it does not check for exceptions, which is a big slow-down in .NET

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜