20190919-3 效能分析
作业要求详见:[https://edu.cnblogs.com/campus/nenu/2019fall/homework/7628]
代码地址:https://e.coding.net/SpringSun/wf.git
要求0 以 战争与和平 作为输入文件,重读向由文件系统读入。连续三次运行,给出每次消耗时间、CPU参数。 (2分)
次数 | 耗时(s) |
1 | 1.193 |
2 | 1.180 |
3 | 1.168 |
平均 | 1.180 |
CPU参数:Intel(R)Core(TM) i5-5200U CPU @2.20 GHz
要求1 给出你猜测程序的瓶颈。你认为优化会有最佳效果,或者在上周在此处做过优化 (或考虑到优化,因此更差的代码没有写出) 。
从字符输入流中读取文本并缓冲字符,由于文本里有大量单词,还需要过滤掉除字母以外的字符,我认为这个会非常耗时。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));// 从字符输入流中读取文本并缓冲字符 List<String> list = new ArrayList<String>(); // 存储过滤后单词的列表 String readLine = null; while ((readLine = br.readLine()) != null) { String[] wordsArr = readLine.split("[^a-zA-Z]"); // 过滤掉除字母以外的字符 for (String word : wordsArr) { if (word.length() != 0) { // 去除长度为0的行 list.add(word); } } }
要求2 通过 profile 找出程序的瓶颈。给出程序运行中最花费时间的3个函数(或代码片断)。要求包括截图。 (5分)
对于笨笨的都不知道啥是profile,更不知道怎么对自己的程序profile。先是问了已经发布博客的同学是怎样做的,然后查询了往届学长学姐的实例,然后下载了一个verysleepys,又在网上找了大量相关资料,感觉不错的推荐看:https://www.cnblogs.com/duanxz/p/3492890.html
本次用的是JDK1.8自带的jvisualvm.exe来进行profile分析,由于程序功能单一,运行比较快,在main函数中加入以下代码,延长程序执行时间,便于及时查看profile分析结果。
Thread.sleep(10000); //测试效能分析
下面分别是main()、TexCount()、WordCount()等函数的CPU、内存占用时间和分布情况。
统过上面两张图即可看出,该功能耗时比较长的是分别是split.()、BufferedReader.readLine()等函数。
//split.()函数比较耗时 String[] wordsArr = readLine.split("[^a-zA-Z]"); // 过滤掉除字母以外的字符
要求3 根据瓶颈,"尽力而为"地优化程序性能。
由于该功能比较单一,所用到的函数不多,不会有太大的性能提升。可做的优化有,去掉没有必要的print,优化了函数调用逻辑,精简了代码量,使得代码可复用等。以下便是优化后的代码片段、耗时表和截图。
public static void main(String args[]) throws InterruptedException { Thread.sleep(10000); //测试效能分析 if ("-d".equals(args[0])){//功能1、2实现: String path = "D:/Project/JAVA/text/" + args[1] + ".txt"; try { textCount(path);// 单个文件过滤单词 } catch (Exception ex) { System.out.println("请输入正确的文件名称,确认文件存在以及文件是否放在D:/Project/JAVA/text/"); } }else if ("-f".equals(args[0])){ //功能3实现: String path1 = args[1]; File file = new File(path1); if (file.isDirectory()) { File[] filelist = file.listFiles(); for (File filePath : filelist) { try { String s = filePath.getPath();// 获取完整路径 System.out.println(filePath.getName());//输出文件名 textCount(s); } catch (Exception ex) { System.out.println("请输入正确的路径,格式:D:/Project/JAVA/text/"); } } } }else if("-s".equals(args[0])){ //功能4实现: try { TxtCount(); } catch (Exception ex) { System.out .println("请输入正确的命令,eg:java WF.WF < a1.txt,确定后文件存在以及文件是否放在*.java文件目录"); } } }
次数 | 耗时(s) |
1 | 1.134 |
2 | 1.126 |
3 | 1.131 |
平均 | 1.130 |
要求4 再次Profile
经过精细化调优代码后,从下面的Profile可以看出CPU和内存耗时有明显的缩短。
要求5 程序运行时间。
期待老师的检验和指导。