作为一个专业的程序员,你写了一段程序,完成了一个功能,似乎达到了用户的要求,其实你心里也没底。
做一个简单的测试, 跑了一个主要流程,基本的功能应该是满足需求的,但是性能呢?

我们需要对程序的性能进行度量,确保性能是满足用户需求的。如果性能不理想,必需要找到瓶颈在哪里。

最近在读狄更斯的小说《双城记》英文原版,既是学习英语,也是领略大师的行文。同时,我想知道大师喜欢用什么词,所以写了一个小程序来统计这部小说的词汇。让我们度量一下这个小程序的性能,看看瓶颈在哪里, 有什么好的方法。

程序示例

需求

设计

用C++ 来写一段小程序,取名为 WordBank , 基本功能就是

  1. 获取总的单词数量: getTotalWordCount();
  2. 获取不重复的单词总数:getUniqueWordCount);
  3. 打印若干个使用频率最高的单词:printTop(int n)
  4. 获取某个单词的使用频度排序号: getWordRank(const std::string& name);
  5. 获取某个单词的使用数量:getWordCount(const std::string& name);

我想看看

  • 大师在这本书中使用了多少词汇
  • 大师用的最多的20个单词
  • "think" 这个单词用了多少次
  • "think" 排在最常使用率排名的多少位

于是,我就写了一个C++ 类 WordBank, 使用 std::map<std::string, int> m_mapWords; 来保存单词的个数,使用 std::vector<std::pair<std::string, int>> m_vecWords; 来保存排过序的单词使用率排名。

#ifndef __WORD_BANK_H__
#define __WORD_BANK_H__#include <cstdint>
#include <string>
#include <map>
#include <set>
#include <vector>class WordBank
{
public:WordBank(const std::string& words_file);int getWordRank(const std::string& name) const;int getWordCount(const std::string& name) const;void sortWords();void printTop(int n) const;int getTotalWordCount() const;int getUniqueWordCount() const;private:bool hasWord(const std::string& word) const;void increaseWordCount(const std::string& word);void addWord(const std::string& word);std::map<std::string, int> m_mapWords;std::vector<std::pair<std::string, int>> m_vecWords; uint32_t m_wordCount;};std::string convertString(const std::string& word);#endif

实现

#include "WordBank.h"
#include <iostream>
#include <fstream>
#include <algorithm>using namespace std;bool comparePair(pair<string, int>& a, pair<string, int>& b)
{ return a.second > b.second;
} WordBank::WordBank(const string & words_file): m_wordCount(0) {ifstream is(words_file.data());if (!is) {throw invalid_argument("unable open file");}string word;while (is >> word) {m_wordCount ++;if (!hasWord(word)) {addWord(word);}else {increaseWordCount(word);}}
}int WordBank::getWordRank(const std::string& word) const {int count = getWordCount(word);if (count == 0) {return 0;}int rank = 1;for (const auto&[key, value] : this->m_mapWords) {if (value > count) {rank++;}}return rank;
}int WordBank::getWordCount(const std::string& word) const {string str = convertString(word.data());auto it = m_mapWords.find(str);if (it != m_mapWords.end()) {return it->second;}return 0;
}int WordBank::getTotalWordCount() const {return m_wordCount;
}int WordBank::getUniqueWordCount() const {return m_mapWords.size();
}bool WordBank::hasWord(const string & word) const {string str = convertString(word.data());auto it = m_mapWords.find(str);if (it != m_mapWords.end()) {return true;}return false;
}
void WordBank::increaseWordCount(const string & word) {string str = convertString(word.data());auto it = m_mapWords.find(str);if (it != m_mapWords.end()) {it->second++;}
}
void WordBank::addWord(const string & word) {string str = convertString(word);if (str.empty()) {return;}//cout << "insert " << word  << " -> " << str << endl;m_mapWords.insert(make_pair(str, 1));
}void WordBank::sortWords() {for (auto& pair : m_mapWords ) { m_vecWords.push_back(pair); } // Sort using comparator function sort(m_vecWords.begin(), m_vecWords.end(), comparePair); } void WordBank::printTop(int n) const {for (auto pair : m_vecWords) {cout << pair.first << ": " << pair.second << endl;if (--n <= 0) {break;}}}string convertString(const string & word) {string str("");for (size_t i = 0; i < word.length(); ++i) {uint8_t ch = word[i];if(ch > 0 && ch < 255 && isalpha(ch)) {str.push_back(tolower(ch));}}return str;
}

测试

#include "WordBank.h"
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <boost/timer/timer.hpp>using namespace std;
using namespace boost::timer;int main(int argc, char *argv[])
{string word_search = "rtp";string word_file = "rfc3550.txt";int topN = 10;if (argc > 1) {word_search = argv[1];cout << "Make statistics for word count and rank: " <<convertString(word_search) << endl;} else {cout << "usage: " << argv[0] << "<search_word> <input_file> <topN>" << endl;cout << "example: " << argv[0] << " " << word_search << " " << word_file << " " << topN <<endl;}if (argc > 2) {word_file = argv[2];cout << "Read file: " << word_file << endl;}if (argc > 3) {topN = atoi(argv[3]);}try {boost::timer::auto_cpu_timer timer;WordBank wordbank(word_file);wordbank.sortWords();std::cout << "wordbank total word count: " << wordbank.getTotalWordCount() << endl;std::cout << "wordbank unique word count: " << wordbank.getUniqueWordCount() << endl;cout << word_search << "'s count=" << wordbank.getWordCount(word_search) << endl;cout << word_search  << "'s rank=" << wordbank.getWordRank(word_search) << endl;cout << "--- top "  << topN << " ---" << endl;wordbank.printTop(topN);} catch(const invalid_argument& e) {cerr << "Caught exeption: " <<e.what() <<endl;}return 0;}

执行结果如下, 双城记总词数为139021 ,共使用了 10984 个单词,最常使用的词是 "the", 而 “think” 这个词用了 120 次,排名 150 位。

./bin/wordbankdemo think A-Tale-of-Two-Cities.txt 20
Make statistics for word count and rank: think
Read file: A-Tale-of-Two-Cities.txt
wordbank total word count: 139021
wordbank unique word count: 10984
think's count=120
think's rank=150
--- top 20 ---
the: 8202
and: 4998
of: 4137
to: 3545
a: 2981
in: 2642
it: 2016
his: 2005
i: 1917
that: 1904
he: 1833
was: 1765
you: 1460
with: 1354
had: 1297
as: 1148
at: 1045
her: 1038
for: 973
him: 9650.079933s wall, 0.060000s user + 0.000000s system = 0.060000s CPU (75.1%)

度量性能

使用 boost 库的 auto_cpu_timer 来计时

剖析性能

使用著名的 valgrind 软件所附带的 callgrind 的剖析性能瓶颈在哪里

sudo apt install valgrind
valgrind --tool=callgrind ./bin/wordbankdemo
sudo apt-get install python3 graphviz# 在 Debian/Ubuntu 安装 python3 和 graphviz
apt-get install python3 graphviz# 在 RedHat/Fedora  安装 python3 和 graphviz
yum install python3 graphviz# 再安装 gprof2dot
pip install gprof2dot# 生成有向图
gprof2dot -f callgrind -n10 -s callgrind.out.816 > valgrind.dot
dot -Tpng valgrind.dot -o valgrind.png

从上图可以看出,其大部分时间花在 WordBank 的构造方法,其中 hasWord, increaseWordCount 这两个方法花了大部分时间, 其中 convertString 和map 的红黑树的 find 方法又占据了大部分时间, 仔细看看这两个方法的调用,其实我们能够做出优化

WordBank::WordBank(const string & words_file): m_wordCount(0) {ifstream is(words_file.data());if (!is) {throw invalid_argument("unable open file");}string word;while (is >> word) {m_wordCount ++;if (!hasWord(word)) {addWord(word);}else {increaseWordCount(word);}}
}
  1. word 可以事先转化 convertString 方法不需要重复调用
  2. hasWordincreaseWordCount 不需要重复查找, 可以把迭代器作为额外参数传入, 或者把 map 的 value 的引用传出来

试着改一下,再重复上述的度量过程, 你能清晰地看出来改进的效果。

代码链接参见

  • https://github.com/walterfan/snippets/blob/master/cpp/inc/WordBank.h
  • https://github.com/walterfan/snippets/blob/master/cpp/src/WordBank.cpp
  • https://github.com/walterfan/snippets/blob/master/cpp/exam/WordBankDemo.cpp

http://www.taodudu.cc/news/show-7203720.html

相关文章:

  • SAT阅读:双城记材料分析
  • noip模拟赛 双城记
  • 【全文检索_03】Lucene 基本使用
  • 《双城记》
  • 双城记 A Tale of Two Cities
  • 开设 AI本科专业 的国内高校一览
  • 2021年全球“美食界”打卡指南整理!中国有多家餐厅、酒吧榜上有名
  • AI开发之——Leonardo—Community Feed模型制作图形(4)
  • 高规格国赛接棒AidLux AI应用竞赛,AidLux邀你来报名赢大奖!
  • 30个网站源码
  • 在线出售域名页面html源码
  • 网站源码
  • 如何选择连锁药店收银管理系统,推荐参考5个原则
  • 连锁店电商“双私域流量”运营解决方案 F2B2b2C解决方案
  • 连锁店收银系统如何帮助鞋店管理好分店?
  • ss 管理系统 php 源码,基于SSM框架下的B/S服装连锁店管理系统,源码分享
  • 连锁企业经营的8大成功密码
  • 基于量子遗传算法的函数寻优算法—MATLAB实现
  • 朋友推荐的一篇文章--寻爱
  • 新站发布——寻爱交友网
  • 英国留学怎么样
  • 留学信息资讯
  • ChatGPT这么火,对留学有什么影响?
  • 国外论坛
  • 傲游网络安全浏览器最新发布,四大企业结安全联盟
  • 阿里钉钉,傻了
  • 武汉大学科傻平差--CosaGPS(以附2.1 Example/Demo 算例)
  • 【新鲜出炉】傻孩子大神关于IAP的一些闲聊
  • 【平差软件学习---科傻】 一、认识和安装科傻
  • 科傻使用体会

C++程序度量驱动调优实例:看狄更斯的双城记,寻找性能瓶颈相关推荐

  1. 智能路由心酸调优路——看推广代码简洁之道的重要性

    智能路由心酸调优路--看推广代码简洁之道的重要性 甜橙金融作为一个日均订单量过千万的面向C端的互联网金融科技公司,525爆点活动订单量更是平时的好几倍,随着公司业务的高速发展,原有的系统架构,对于业务 ...

  2. 浅谈Spark应用程序的性能调优

    浅谈Spark应用程序的性能调优 :http://geek.csdn.net/news/detail/51819 下面列出的这些API会导致Shuffle操作,是数据倾斜可能发生的关键点所在  1. ...

  3. 对 Web 应用程序进行性能调优

    这是一位IBM专家对 Web 应用程序进行性能调优 转载于:https://www.cnblogs.com/zwh-Seeking/articles/11059351.html

  4. 被法拉第夸、狄更斯为她读诗、英王参加她的成人礼,程序员祖师的人生有多传奇?...

    作者 | Aholiab 出品 | 程序人生 (ID:coder _life) 阿达·拉芙莱斯,一个IT圈里人人都听过的名字.被称为「程序员的开山鼻祖」,但也存在着旷日持久的争议. 探索关于Ada的一 ...

  5. Android性能调优实例

    本文主要分享自己在appstore项目中的性能调优点,包括 同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等. 一.性能瓶颈点 整个页面主要由6个Page的ViewPager,每个 ...

  6. Oracle调优之看懂Oracle执行计划

    1.文章写作前言简介 之前曾经拜读过<收获,不止sql调优>一书,此书是国内DBA写的一本很不错的调优类型的书,是一些很不错的调优经验的分享.虽然读了一遍,做了下读书笔记,觉得很有所收获, ...

  7. 深入浅出JVM调优,看完你就懂

    深入浅出JVM调优 基本概念: JVM把内存区分为堆区(heap).栈区(stack)和方法区(method).由于本文主要讲解JVM调优,因此我们可以简单的理解为,JVM中的堆区中存放的是实际的对象 ...

  8. JVM解读-性能调优实例

    2019独角兽企业重金招聘Python工程师标准>>> JVM性能调优 1 堆设置调优 年轻代大小选择 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选 ...

  9. win7查看tomcat端口_想研究Tomcat性能调优,看这篇就够了

    一.下载地址 https://tomcat.apache.org/download-80.cgi 二.安装步骤 将安装包 apache-tomcat-8.5.39.tar.gz 上传至服务器 /usr ...

最新文章

  1. shell中竖线的作用_如何在 Linux 中安装、配置和使用 Fish Shell?
  2. 106:HttpResponse对象讲解
  3. cv2.waitKey(x)解析
  4. Eclipse 常用快捷键-java
  5. IntelliJ IDEA中日志分类显示设置
  6. 蒙特卡洛方法_基本理论-蒙特卡洛方法与定积分
  7. JQuery 方法查询大全
  8. 复练-关于面试的科技树-简历的提升、问答环节
  9. Spring框架知识要点总结(第一天)
  10. 乘法逆元(ex_gcd和同余定理)
  11. Android源码刷机步骤
  12. 2020年中国电力线载波通信行业发展现状及竞争格局分析,国家电网持续推进电网转型升级,配电自动化覆盖率达到90%「图」
  13. 中交一公局二公司全面推进章管家 印章智慧管理转型在即
  14. Xilinx FPGA “打一拍”“打两拍”以及IOB含义
  15. 遇到长GC停顿、CPU满载、内存泄露、JVM崩溃等高频问题,看这里!
  16. 大数据技术之Hadoop(入门)概述、运行环境搭建、运行模式
  17. getopt.h和getopt(),getopt_long()等函数
  18. Amazon DynamoDB
  19. 如何在手机上收发邮件?
  20. FreeModbus

热门文章

  1. 记录一下我在刷题的过程中发现我没记住的知识
  2. 外卖平台的设计与实现
  3. android 手机 对比,四款消费级Android对比评测
  4. TextMate使用心得
  5. 2021年端午节放假放几天,放假通知如何用便签提醒
  6. C# 保护进程不被结束(源代码)防任务管理器结束进程
  7. Android模仿微信UI界面
  8. nubia基于android深度定制的ui,FiT2.0突破新维度 nubia UI 4.0系统体验
  9. 比pigz性能更好的pzstd
  10. 如何获取每月第一个/最后一个交易日