Lab5实验总结

lab5首先要求我们比对各种输入输出方式的优劣。我测试了 bufferedreader读, Files.lines、Stream读,scnner读,bufferedwriter写,outputstream写,channel写这六种IO。
通过注入输出代码和获取当前时间代码,在读入/写出完成时计算时间差值并输出,即可统计I/O所用的时间。
以表格方式对比输入输出的效率

在这里插入图片描述
以图形对比不同I/O的性能
在这里插入图片描述

由图表可见,Java8 Stream读最快,scanner最慢,bufferedwriter写最快,outputstream写最慢。
但是scanner使用比较方便,可以作为casual use,比如写个主函数测试的时候还是比较方便的,大规模的数据输入就不要使用这个了。bufferedwriter写入文件比较快,我觉得使用也比较方便,适合逐行写文件。
第二个任务是使用各种工具分析内存。
1.在eclipse中的run configuration中可以直接加命令行参数运行程序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三个参数分别为:

GC前该内存区域使用容量->GC后该内存区域使用容量(该内存区域总容量)

2.在cmd中使用jstat、jmap等工具分析内存
如果之前配置了环境变量,可以直接在cmd中输入命令,如果没有,则可以进入jdk的bin目录再运行这些命令

3.使用visualVM进行可视化分析
我使用的是1.8.0版本的JDK,在bin目录中可以直接找到jvisualvm.exe,运行即可。
在这里插入图片描述
使用visualVM进行CPU profiling时,运行程序需要加上-Xverify:none这个参数,不然我的跑不出结果,会在控制台显示连接错误。

分析:读写文件时,堆内存不够时,发生垃圾回收,年轻代内存不够时,发生Minor GC,当年轻代转入老年代使老年代空间不够时,发生Full GC。

读操作时,不断产生垃圾,主要源于读入时临时的String,数组和排序的MAP、记录已存标签的集合等等,也不断读入数据,新建对象。当Eden区满时,触发Minor GC。Minor GC进行垃圾回收后,会把存活下来的对象拷贝到s0或s1中的一个,并且提升他们的代数,然后下次GC时清空这个survivor区,拷贝到另一个区,轮换进行。当对象的代数达到一定阈值,就会被移到老年代。随着Minor GC的不断进行,不断有新的对象被转入老年代,当老年代空间不足时,进行Full
GC。

写操作时,同样产生了一些临时的字符串,他们使Eden空间不足,于是发生了Minor GC,进而发生了Full GC。

这个实验最难的部分应该就是如何优化了。我在做的时候优化主要是减少不必要的遍历,存储一些查询的图来减少每次查询的复杂度,改进核心算法等。
这个实验也告诉我们平时书写代码的时候需要保持好的习惯,不能为了逻辑上一时的方便就采取非常粗暴的算法和写法,数据规模扩大时就跑不动了。好的习惯包括:1)如果一个observer非常常用,比如通过姓名String查询用户,那么最好存储一个索引 2)如果一个算法开销大,而且每次都要用,最好将结果存储起来,比如迪杰斯特拉算法生成一个图,比一次次广度遍历显然要好,而SPFA算法则更快。这种比较复杂的计算不能用太naïve的算法。3)使用Java自带的数据结构,比如基于红黑树的treemap来维持有序性等,反正比我自己写的好。
对于空间复杂性,不要每次new新的String,对于重复的数据可以使用同一个对象表示他们。比如一直使用“CCW”这样的表示,他们就会指向同一个对象,减少空间的冗余。

猜你喜欢

转载自blog.csdn.net/qq_43351085/article/details/93401940
今日推荐