百度面试题及我的解答(5)-0 优化性能
2009-12-06 18:22
351 查看
本次的主题是优化TraverseTbl。
代码主要包括两部分:
1. 一部分是把单词从文件读入到Hash表的Add部分。
2. 第二部分是遍历hash表,找出所有的变位词,并输出。
下表是主要时间消耗函数在step5函数,dict4输入时性能统计数据(VS2005 Team Suit)。从图中可以看出,TraverseTbl函数消耗的时间最多,所以本次优化的主题就在TraverseTbl。
首先说明一下从step4->step5的主要变化。
1. 在step4的基础上修改了输出函数。对于变位词,不再输出所有词,而是每个单词只输出一次。
2. step4和step5使用的都是vector来保存临时使用的变位词列表(用于检索这个词是否已经出现过)。
Step5使用样本dict4的性能测试数据。这里只摘录了TraverseTbl 函数的性能数据。
仔细阅读下表,可以发现vector各种操作占用了大量的CPU时间,看来在这里STL成为了性能瓶颈了。
在前面分析的基础上为step6做优化:step6放弃了所有的STL,使用了原生数组来保存临时使用的变位词列表,代码复杂了很多。
step6,使用dict4(和上面的数据使用同样的输入样本)输入的性能数据请见下表。从数据可以看出TraverseTbl使用时间大幅减少。已经不再是整个程序的性能瓶颈。
再看TraverseTbl的性能数据,可以看出修改后主要的CPU时间都消耗在了输出了。这里优化的余地很小了。
关于标准库ostream输出,有一个小的优化技巧:
C++ Primter中说"endl“会触发输出缓冲区flush,所以在换行的时候使用"/n“在输出密集时可以极大的减少CPU时间。
最后给出GetTickCount记录的优化前后的性能数据比较。
附: step5 & step6的代码单独发文给出。
代码主要包括两部分:
1. 一部分是把单词从文件读入到Hash表的Add部分。
2. 第二部分是遍历hash表,找出所有的变位词,并输出。
下表是主要时间消耗函数在step5函数,dict4输入时性能统计数据(VS2005 Team Suit)。从图中可以看出,TraverseTbl函数消耗的时间最多,所以本次优化的主题就在TraverseTbl。
调用次数 | 已用包含时间 | 应用程序包含时间 | |
HashMethod1::Add(char *) | 11584 | 41.15813 | 41.15813 |
HashMethod1::TraverseTbl(void (*)(class WORD_NODE *,class std::basic_ostream<char,struct std::char_traits<char> > &),class std::basic_ostream<char,struct std::char_traits<char> > &) | 1 | 246.404109 | 246.404109 |
std::basic_istream<char,struct std::char_traits<char> >::getline(char *,int) | 11584 | 10.345872 | 10.345872 |
1. 在step4的基础上修改了输出函数。对于变位词,不再输出所有词,而是每个单词只输出一次。
2. step4和step5使用的都是vector来保存临时使用的变位词列表(用于检索这个词是否已经出现过)。
Step5使用样本dict4的性能测试数据。这里只摘录了TraverseTbl 函数的性能数据。
仔细阅读下表,可以发现vector各种操作占用了大量的CPU时间,看来在这里STL成为了性能瓶颈了。
已用包含时间 | 应用程序包含时间 | |
Step5TraverseProcess(class WORD_NODE *,class std::basic_ostream<char,struct std::char_traits<char> > &) | 243.778101 | 243.778101 |
@_RTC_CheckStackVars@8 | 0.122864 | 0.122864 |
__RTC_CheckEsp | 0.002778 | 0.002778 |
std::_Vector_const_iterator<char *,class std::allocator<char *> >::operator<(class std::_Vector_const_iterator<char *,class std::allocator<char *> > const &) | 2.992718 | 2.992718 |
std::_Vector_const_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::operator<(class std::_Vector_const_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> > const &) | 2.546526 | 2.546526 |
std::_Vector_iterator<char *,class std::allocator<char *> >::_Vector_iterator<char *,class std::allocator<char *> >(void) | 0.439095 | 0.439095 |
std::_Vector_iterator<char *,class std::allocator<char *> >::~_Vector_iterator<char *,class std::allocator<char *> >(void) | 16.543602 | 16.543602 |
std::_Vector_iterator<char *,class std::allocator<char *> >::operator*(void) | 0.914471 | 0.914471 |
std::_Vector_iterator<char *,class std::allocator<char *> >::operator++(int) | 21.69992 | 21.69992 |
std::_Vector_iterator<char *,class std::allocator<char *> >::operator=(class std::_Vector_iterator<char *,class std::allocator<char *> > const &) | 3.513451 | 3.513451 |
std::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >(void) | 0.128564 | 0.128564 |
std::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::~_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >(void) | 27.025921 | 27.025921 |
std::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::operator*(void) | 2.336124 | 2.336124 |
std::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::operator++(int) | 37.61024 | 37.61024 |
std::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::operator=(class std::_Vector_iterator<class WORD_NODE *,class std::allocator<class WORD_NODE *> > const &) | 3.370732 | 3.370732 |
std::operator<<<struct std::char_traits<char> >(class std::basic_ostream<char,struct std::char_traits<char> > &,char const *) | 17.054776 | 17.054776 |
std::vector<char *,class std::allocator<char *> >::~vector<char *,class std::allocator<char *> >(void) | 3.171833 | 3.171833 |
std::vector<char *,class std::allocator<char *> >::begin(void) | 6.04406 | 6.04406 |
std::vector<char *,class std::allocator<char *> >::end(void) | 10.862848 | 10.862848 |
std::vector<char *,class std::allocator<char *> >::push_back(char * const &) | 27.360623 | 27.360623 |
std::vector<char *,class std::allocator<char *> >::vector<char *,class std::allocator<char *> >(void) | 0.692344 | 0.692344 |
std::vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::~vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >(void) | 0.910566 | 0.910566 |
std::vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::begin(void) | 5.392134 | 5.392134 |
std::vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::end(void) | 12.87197 | 12.87197 |
std::vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::push_back(class WORD_NODE * const &) | 33.516505 | 33.516505 |
std::vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >::vector<class WORD_NODE *,class std::allocator<class WORD_NODE *> >(void) | 0.24984 | 0.24984 |
THUNK:strcmp | 1.551301 | 1.551301 |
step6,使用dict4(和上面的数据使用同样的输入样本)输入的性能数据请见下表。从数据可以看出TraverseTbl使用时间大幅减少。已经不再是整个程序的性能瓶颈。
已用包含时间 | 应用程序包含时间 | |
HashMethod1::TraverseTbl(void (*)(class WORD_NODE *,class std::basic_ostream<char,struct std::char_traits<char> > &),class std::basic_ostream<char,struct std::char_traits<char> > &) | 10.02689 | 10.02689 |
std::basic_ifstream<char,struct std::char_traits<char> >::`vbase destructor'(void) | 0.002275 | 0.002275 |
std::basic_ifstream<char,struct std::char_traits<char> >::basic_ifstream<char,struct std::char_traits<char> >(void) | 0.003745 | 0.003745 |
std::basic_ifstream<char,struct std::char_traits<char> >::close(void) | 0.038395 | 0.038395 |
std::basic_ifstream<char,struct std::char_traits<char> >::is_open(void) | 0.000133 | 0.000133 |
std::basic_ifstream<char,struct std::char_traits<char> >::open(char const *,int,int) | 0.090127 | 0.090127 |
std::basic_istream<char,struct std::char_traits<char> >::getline(char *,int) | 14.460544 | 14.460544 |
std::basic_ofstream<char,struct std::char_traits<char> >::`vbase destructor'(void) | 0.009248 | 0.009248 |
std::basic_ofstream<char,struct std::char_traits<char> >::basic_ofstream<char,struct std::char_traits<char> >(char const *,int,int) | 0.308374 | 0.308374 |
std::basic_ofstream<char,struct std::char_traits<char> >::close(void) | 1.234804 | 1.234804 |
std::basic_ostream<char,struct std::char_traits<char> >::operator<<(class std::basic_ostream<char,struct std::char_traits<char> > & (*)(class std::basic_ostream<char,struct std::char_traits<char> > &)) | 0.168245 | 0.168245 |
std::basic_ostream<char,struct std::char_traits<char> >::operator<<(unsigned long) | 1.05469 | 1.05469 |
std::ios_base::eof(void) | 0.581269 | 0.581269 |
关于标准库ostream输出,有一个小的优化技巧:
C++ Primter中说"endl“会触发输出缓冲区flush,所以在换行的时候使用"/n“在输出密集时可以极大的减少CPU时间。
调用次数 | 已用包含时间 | 应用程序包含时间 | |
HashMethod1::TraverseTbl(void (*)(class WORD_NODE *,class std::basic_ostream<char,struct std::char_traits<char> > &),class std::basic_ostream<char,struct std::char_traits<char> > &) | 1 | 10.02689 | 10.02689 |
__RTC_CheckEsp | 551 | 0.000078 | 0.000078 |
Step6TraverseProcess(class WORD_NODE *,class std::basic_ostream<char,struct std::char_traits<char> > &) | 550 | 7.864288 | 7.864288 |
@_RTC_CheckStackVars@8 | 550 | 0.007252 | 0.007252 |
__RTC_CheckEsp | 550 | 0.00013 | 0.00013 |
std::operator<<<struct std::char_traits<char> >(class std::basic_ostream<char,struct std::char_traits<char> > &,char const *) | 6048 | 6.360357 | 6.360357 |
THUNK:memset | 1100 | 0.070764 | 0.070764 |
THUNK:strcmp | 46076 | 0.702009 | 0.702009 |
step5 | step6 | |||
第一次 | 第二次 | 第一次 | 第二次 | |
添加单词到Hash表(Add,getline,sort) | 1061 | 1061 | 1170 | 1061 |
遍历hash表输出变位词 | 4977 | 4961 | 281 | 249 |
step5: 使用标准库的vector保存所有零时的变位词,使用iterator遍历变位词表 | ||||
step6: 使用普通数组保存所有零时的变位词,数组遍历变位词表 |
相关文章推荐
- 百度面试题及我的解答(5)-1 找出下一步需要优化的内容
- SQL 问题与解答 - 数据库移动、性能优化、备份和镜像
- 面试题:如何优化ListView的性能?
- 一道淘汰85%面试者的百度开发者面试题——解题、参考答案和优化思路
- 性能优化-有关Web性能优化的十种方法(面试题)
- 百度面试题及我的解答(1)
- 百度面试题及我的解答(2)
- 百度面试题及我的解答(4)
- 百度面试题及我的解答(5)-2 step5 & step6 代码
- StringBuilder和StringBuffer解析(百度面试题优化须要用到的)
- 李洪强经典面试题 154- 性能优化
- SQL 问题与解答 - 数据库移动、性能优化、备份和镜像
- 整型数组处理算法(九)给定任意一个正整数,求比这个数大且最小的“不重复数”(性能优化)[2014百度笔试题]
- sam 百度面经的问题总结(2) 性能优化
- [历年IT面试题]百度2014研发类校园招聘笔试题解答
- 做百度优化常见的十个问题及解答
- 百度面试题:自己实现strlen,考虑32位,64位机器,考虑性能
- 帮你解答百度优化十个为什么?
- 整型数组处理算法(九)给定任意一个正整数,求比这个数大且最小的“不重复数”(性能优化)[2014百度笔试题]
- Android面试题-与性能优化相关面试题一