Lab5遇到的问题和解决途径

读取文件时间过长

一开始在用Lab3的代码读取文件时,读取时间超过了半个多小时,读取时间过长,因此寻找原因。
首先观察到在建图的边和点的判断中,有循环遍历整个集合来看是否有重复的边或顶点的label,有通过逐个拷贝来防止内存泄漏(深拷贝返回edges和vertices集合),有checkRep的assert检查,都会极大的降低程序的效率,因此将这些部分注释掉。
但是注释掉后程序运行的时间并没有很快,(达到20-30秒的水平)。
进一步寻找原因:
使用VisualVM找到占用时间较长的代码:
这里写图片描述
发现HashSet.add()函数占用时间较长,但是为什么呢?我想到了数据结构中讲到的在哈希表中插入元素,如果当前值已经有元素了,那么会采用线性插补法来进行哈希值的分配。
由于我在vertex和edge的类中,为了使在等价时equals函数和hashcode函数有相同的表现,我将hashcode都设置为了常数。(一开始我设置的是label的长度,但是有在两个顶点或边应该相等但equals为真而hashcode不一样的情况。)
这样会导致在向集合中插入元素时,将会每次都向后寻找下一个位置,使其效率大大降低。
将vertex和edge类中的hashcode修改为label.hashcode()+(int)weight,并将equals方法修改为判断label是否相等。
在修改后执行读文件并且建图的时间大大缩短,达到预期的要求。

Nio读写文件

我使用了ppt中的代码来写文件:

FileChannel ch = FileChannel.open(Paths.get(args[0]), StandardOpenOption.WRITE)

但是在运行时会有文件不存在的错误,程序并不会在文件不存在时建立一个新的文件,因此修改为:

FileOutputStream fos = null;
fos = new FileOutputStream(new File(filepath));
FileChannel channel = fos.getChannel();

通过File来获取当前文件对象,这样可以在没有当前名称的文件存在时建立一个新的文件来供写入。
使用nio的Channel来读取文件时由于需要按行分割,我们要用多余的代码来处理换行符。

FileChannel.open(Paths.get(filepath), StandardOpenOption.READ);

之后我们使用ByteBuffer作为字符的缓冲区,使用temp字节数组用于存储不完整的行的内容,判断是否出现了换行符,注意这要区分LF-\n,CR-\r,CRLF-\r\n,这里判断\n。如果出现了换行符,将temp中的内容与换行符之前的内容拼接,将换行符之后的内容(去除换行符)存到temp中。如果没出现换行符,则将内容保存到temp中。
但是这种方法写起来复杂并且容易出错,因此我在博客上看到了一种新的方法,使用Files.readAllLines()返回一个字符串数组,然后我们简单的遍历这个数组就可以方便的构建图。

实验总结

代码看起来美是指代码的结构和规范,运行起来很美指的是程序的性能。两者之间的关系是联系在一起的,在有限的时间中,我更注重运行起来很美,因为性能是一个重要的指标。
FindBugs和CheckStyle确实帮助了我找到了代码中的一些平时没有注意的规范问题,相比我的同学来说,我的错误较少,说明我平时养成了良好的习惯,但是这些平时没有注意到的问题让我对以后的代码要求更加严格。
Java随着时代在进步,提供了不同的IO方式供不同的需求的场景来使用,体现了JDK自身代码的逐渐优化过程。
JVM的GC与计算机系统的内容相比,将多种GC方式综合到一起,引入了young generation和old generation,并且对不同的区域应用不同的GC方式,提高了效率,充分利用了各种GC方式的优点。值得我们学习。
通过配置JVM内存分配和GC参数来提高程序运行性能,让我们可以根据自己程序的特点来进行优化,可以让程序的性能得到很大的提升。例如,程序每秒都有大约400M的海量短命对象产生,那么我们可以采用CMS收集器,并且对MaxTenuringThreshold(生代对象撑过过多少次minor gc才进入年老代的设置)设置为较高参数。得到了很大的性能优化。
通过Memory Dump进行程序性能的分析,VisualVM和MAT这两个工具提供了很强大的分析功能。我已经体验到了使用它们发现程序热点以进行程序性能优化的好处,例如我发现构建图的过程中占用时间较长的为HashSet.add()函数,让我对vertex和edge类的hashcode进行修改了提高了程序的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值