C# 异常会降低性能吗?
我的应用程序遍历目录树,并在每个目录中尝试打开具有特定名称的文件(使用C# 异常会降低性能吗?,c#,.net,exception-handling,C#,.net,Exception Handling,我的应用程序遍历目录树,并在每个目录中尝试打开具有特定名称的文件(使用file.OpenRead())。如果此调用抛出FileNotFoundException,则它知道该文件不存在。我是否希望在此之前调用File.Exists()来检查文件是否存在?这会更有效吗?更新 我在一个循环中运行这两个方法,并对每个方法进行计时: void throwException() { try { throw new NotImplementedException();
file.OpenRead()
)。如果此调用抛出FileNotFoundException
,则它知道该文件不存在。我是否希望在此之前调用File.Exists()
来检查文件是否存在?这会更有效吗?更新
我在一个循环中运行这两个方法,并对每个方法进行计时:
void throwException()
{
try
{
throw new NotImplementedException();
}
catch
{
}
}
void fileOpen()
{
string filename = string.Format("does_not_exist_{0}.txt", random.Next());
try
{
File.Open(filename, FileMode.Open);
}
catch
{
}
}
void fileExists()
{
string filename = string.Format("does_not_exist_{0}.txt", random.Next());
File.Exists(filename);
}
Random random = new Random();
以下是未连接调试程序且未运行发布版本的结果:
方法每秒迭代次数
ThroweException 10100
fileOpen 2200
文件存在11300
抛出异常的成本比我预期的要高很多,对不存在的文件调用FileOpen似乎比检查不存在的文件的存在慢得多
在文件通常不存在的情况下,检查文件是否存在似乎更快。我可以想象,在相反的情况下——当文件通常存在时,您会发现捕获异常的速度更快。如果性能对应用程序至关重要,我建议您根据实际数据对这两种方法进行基准测试
正如在其他答案中提到的,请记住,即使在打开文件之前检查文件是否存在,如果有人在检查文件是否存在后但在打开文件之前删除了文件,也应注意竞争条件。您仍然需要处理异常。一般来说,异常“提高”了系统的整体“性能”
无论如何,在您的示例中,最好使用File.Exists…这种行为真的是例外吗?如果是预期的,您应该使用If语句进行测试,而不使用任何异常。性能不是此解决方案的唯一问题,从您尝试执行的声音来看,性能不应该是一个问题。因此,风格和良好的方法应该是该解决方案关注的事项
因此,总而言之,由于您预期某些测试会失败,请使用文件.Exists进行检查,而不是在事后捕获异常。当然,您仍然应该捕获可能发生的其他异常。不,不要。如果使用File.Exists,则会引入并发问题。如果您编写了此代码:
if file exists then
open file
然后,如果在您选中file.Exists和实际打开文件之前,另一个程序删除了您的文件,则该程序仍将抛出异常
第二,即使文件存在,也不意味着您可以实际打开该文件,您可能没有打开该文件的权限,或者该文件可能是只读文件系统,因此无法以写模式打开,等等
文件I/O比异常昂贵得多,不需要担心异常的性能
编辑:
Linux下Python中存在基准测试异常vs
import timeit
setup = 'import random, os'
s = '''
try:
open('does not exist_%s.txt' % random.randint(0, 10000)).read()
except Exception:
pass
'''
byException = timeit.Timer(stmt=s, setup=setup).timeit(1000000)
s = '''
fn = 'does not exists_%s.txt' % random.randint(0, 10000)
if os.path.exists(fn):
open(fn).read()
'''
byExists = timeit.Timer(stmt=s, setup=setup).timeit(1000000)
print 'byException: ', byException # byException: 23.2779269218
print 'byExists: ', byExists # byExists: 22.4937438965
我不知道效率如何,但我更喜欢文件存在检查。问题是可能发生的所有其他事情:错误的文件句柄,等等。如果您的程序逻辑知道有时文件不存在,并且您希望现有文件与不存在的文件具有不同的行为,请使用file.Exists。如果其不存在与其他文件相关的异常相同,则只需使用异常处理
- --关于如何更好地使用异常的更多信息
如果File.Exists检查提高了性能,则取决于文件存在的可能性。如果它可能存在,则不要使用File.exists,如果它通常不存在,则附加检查将提高性能。是的,您应该使用File.exists。异常应用于不控制程序正常流的异常情况。在您的情况下,不存在文件不会发生异常情况。因此,您不应该依赖异常 更新: 所以每个人都可以自己尝试,我将发布我的测试代码。对于不存在的文件,依赖File.Open为您引发异常比使用File.Exists检查要糟糕50倍左右
class Program
{
static void Main(string[] args)
{
TimeSpan ts1 = TimeIt(OpenExistingFileWithCheck);
TimeSpan ts2 = TimeIt(OpenExistingFileWithoutCheck);
TimeSpan ts3 = TimeIt(OpenNonExistingFileWithCheck);
TimeSpan ts4 = TimeIt(OpenNonExistingFileWithoutCheck);
}
private static TimeSpan TimeIt(Action action)
{
int loopSize = 10000;
DateTime startTime = DateTime.Now;
for (int i = 0; i < loopSize; i++)
{
action();
}
return DateTime.Now.Subtract(startTime);
}
private static void OpenExistingFileWithCheck()
{
string file = @"C:\temp\existingfile.txt";
if (File.Exists(file))
{
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
}
private static void OpenExistingFileWithoutCheck()
{
string file = @"C:\temp\existingfile.txt";
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
private static void OpenNonExistingFileWithCheck()
{
string file = @"C:\temp\nonexistantfile.txt";
if (File.Exists(file))
{
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
}
private static void OpenNonExistingFileWithoutCheck()
{
try
{
string file = @"C:\temp\nonexistantfile.txt";
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
catch (Exception ex)
{
}
}
}
类程序
{
静态void Main(字符串[]参数)
{
TimeSpan ts1=TimeIt(使用Check打开现有文件);
TimeSpan ts2=TimeIt(打开现有文件而不检查);
TimeSpan ts3=TimeIt(使用Check打开不存在的文件);
TimeSpan ts4=TimeIt(打开不存在的文件而不检查);
}
专用静态时间跨度TimeIt(操作)
{
int loopSize=10000;
DateTime startTime=DateTime.Now;
for(int i=0;iclass Program
{
static void Main(string[] args)
{
TimeSpan ts1 = TimeIt(OpenExistingFileWithCheck);
TimeSpan ts2 = TimeIt(OpenExistingFileWithoutCheck);
TimeSpan ts3 = TimeIt(OpenNonExistingFileWithCheck);
TimeSpan ts4 = TimeIt(OpenNonExistingFileWithoutCheck);
}
private static TimeSpan TimeIt(Action action)
{
int loopSize = 10000;
DateTime startTime = DateTime.Now;
for (int i = 0; i < loopSize; i++)
{
action();
}
return DateTime.Now.Subtract(startTime);
}
private static void OpenExistingFileWithCheck()
{
string file = @"C:\temp\existingfile.txt";
if (File.Exists(file))
{
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
}
private static void OpenExistingFileWithoutCheck()
{
string file = @"C:\temp\existingfile.txt";
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
private static void OpenNonExistingFileWithCheck()
{
string file = @"C:\temp\nonexistantfile.txt";
if (File.Exists(file))
{
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
}
private static void OpenNonExistingFileWithoutCheck()
{
try
{
string file = @"C:\temp\nonexistantfile.txt";
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
{
}
}
catch (Exception ex)
{
}
}
}
Dim Files() as string = System.IO.Directory.GetFiles("C:\", "SpecificName.txt", IO.SearchOption.AllDirectories)