StringTable的性能调优
1、通过-XX:StringTableSize=桶个数调整
我们前面说过StringTable是靠我们的HashTable来实现的。即,当我们的空间足够大的时候,我们的数据就会比较分散,查询的效率也会因此降低,反之,当我们的空间比较小的时候,我们的数据就会比较集中,查询的效率也会因此提高。当然了,StringTable 的空间大小并不是越小越好,太小了,一直进行垃圾回收,导致经常要删除老数据,添加新数据等问题也很难受。要是那些个老数据刚删掉没多久就要用到了呢。
这里,我们以黑马程序员的代码教程为例:
读取linux.words文件数据,里面包含了48w+个单词,,我们利用循环读取每一个单词并存入串池中,直到读取结束退出循环。最终输出花费的时间(单位是秒,ms)。
运行结果:(花费0.4s,桶的大小是200000)
桶的大小:
这里其实已经做过优化了,即,通过虚拟机命令 -XX:StringTableSize=200000 将StringTable桶的数量设置为了200,000 。如果不做这种优化的话,那么,耗费的时间如下:(0.618s,桶的默认大小是60013个。)
我们再做个测试,将桶的大小设置为1009,运行结果如下:可以看到,他花费了12秒有余。
总结:如果程序涉及到的字符串足够多的话,那么可以适当调大StringTable的桶的大小,优化性能。
2、考虑是否将字符串对象入池
假如现在让我们存储地球上每个人的家庭住址,我们知道,其实有很多人是住一起的,他们的住址其实没有必要重复存取对吧,而且,我们的家庭住址信息明显就是一个字符串,如果我们让字符串对象入池,那么其实可以省去很多的内存。下面,我们还是套用黑马程序员的代码例子:
将刚才的那些单词循环读取10次,如此,每个单词都肯定会重复10次,这里,为了防止垃圾回收,黑马的教程还加了一个ArrayList来存储对象。
运行后,我们使用jconsole来实时监测我们的内存使用情况:
下图是读取文件前字符串的占用情况:
读取后内存占用情况如下:(可以看到,字符串和char数组的内存飙升了很多。两者想加大概占用了300M的内存。)
然后,我们修改一下,我们每次在将读取到的单词放到ArrayList之前,我们都让他执行intern()方法,将该字符串对象放到串池中。
运行后,char数组和字符串的内存占用只有不到40M。(相比之前重复的300M,少了260M有余。)
总结:当我们的系统数据会出现重复字符串的情况下,我们可以让我们对应的字符串对象入池,来减少内存的占用。