一直都不知道异常的效率损失有多大,在程序中都一直避免使用异常。虽然网上说一个好的C++实现,使异常造成的效率可以减小到5%,然而《C++程序设计语言》一书中指出,理论上一个好的C++实现,可以不会造成效率损失。异常的效率损失到底如何呢,为了搞懂这个东西,我写了如下三个测试程序:
normal.cpp 不使用try语句
try_with_no_exception.cpp 使用try语句,但不抛出异常
try_with_exception.cpp 使用try语句,且抛出异常
这里贴出这三个文件的代码
normal.cpp #include <iostream> #include <ctime> u sin g namespace std;
void normal(const int count) { long k = 0; clock_t start = clock();
for (int j=0; j<count; j++) { k++; k = k % count; }
clock_t end = clock(); double last_time = double(end - start) / CLOCKS_PER_SEC;
cout<<"normal() last time is "<<last_time<<endl; cout<<k<<endl; // 防止for循环被优化了 }
int main(int argc, char **argv) { int count = 1000000; if (argc == 2) { count = atoi(argv[1]); }
normal(count);
return 0; };
try_with_no_exception.cpp #include <iostream> #include <ctime> u sin g namespace std;
void try_with_no_exception(const int count) { long k = 0; clock_t start = clock();
for (int j=0; j<count; j++) { try { k++; k = k % count; } catch (int e) { /// do nothing } }
clock_t end = clock(); double last_time = double(end - start) / CLOCKS_PER_SEC;
cout<<"try_with_no_exception() last time is "<<last_time<<endl; cout<<k<<endl; // 防止for循环被优化了 }
int main(int argc, char **argv) { int count = 1000000; if (argc == 2) { count = atoi(argv[1]); }
try_with_no_exception(count);
return 0; };
try_with_exception.cpp #include <iostream> #include <ctime> u sin g namespace std;
void try_with_exception(const int count) { long k = 0; clock_t start = clock();
for (int j=0; j<count; j++) { try { k++; k = k % count; throw 10; } catch (int e) { /// do nothing } }
clock_t end = clock(); double last_time = double(end - start) / CLOCKS_PER_SEC;
cout<<"try_with_exception() last time is "<<last_time<<endl; cout<<k<<endl; // 防止for循环被优化了 }
int main(int argc, char **argv) { int count = 1000000; if (argc == 2) { count = atoi(argv[1]); }
try_with_exception(count);
return 0; };
|
以上三个源程序,当count为10000000,经过测试,得到测试结果
| AIX | Lin ux | Wind ows |
normal | 0.357904 | 0.39 | 0.23 |
0.356317 | 0.39 | 0.23 | |
0.357617 | 0.39 | 0.23 | |
try_with_no_exception | 0.35757 | 0.39 | 0.24 |
0.350602 | 0.39 | 0.23 | |
0.34906 | 0.39 | 0.24 | |
try_with_exception | 22.0354 | 39.53 | 29.151 |
22.0163 | 38.59 | 30.593 | |
22.0458 | 38.97 | 30.754 |
由测试数据可以看出,不管是在AIX、Linux、Windows上,不使用try和使用try但未抛出异常的情况下,所用的时间差不多, Windows下有些许损失,大概可以按如下的公式计算效率损失 ((0.24+0.23+0.24)/3 - (0.23+0.23+0.23)/3) / (0.23+0.23+0.23)/3 = 1%
Linux上所用时间完全一样,可以理解为没有损失。
AIX上使用try语句时的时间还要少些,这个具体不知道是什么回事,但可以理解为没有效率损失吧。
在抛出异常后,AIX上的效率损失 (22.0354+22.0163+22.0458) / (0.357904+0.356317+0.357617) = 61.67
Linux上的效率损失 (39.53+38.59+38.97) / (0.39+0.39+0.39) = 100.08
Windows上的效率损失 (29.151+30.593+30.754) / (0.23+0.23+0.23) = 131.16
由测试结果可以看出,异常真正的效率损失是在有异常抛出时才会发生。而未抛出异常的try语句块,效率是不会有所损失的。在实际抛出异常时,各个实现的效率损失是不一样的,xlC的损失是60倍左右,g++的损失是100倍,vs2005的损失是130倍左右。这个只是针对异常类型为int的,其它类型(如用户定义的异常类型)的异常损失可能又不一样。
所以,个人觉得,在异常发生时,如果不需要修复错误,也不想要其继续运行,而只是程序必须要处理这种错误情况,处理方法可以是终止程序或是立即获取用户帮助,那么可以采用异常的方式,因为这种情况下,效率的损失是无关重要的。