Java性能优化之影响性能的那些细节原创
3年前
5456411
CRUD麻木了吗?被xxx吐槽系统慢吗?你真的了解你的代码吗?今天聊聊一些关于java性能的细节。
部分内容来自这个网站:http://java-performance.com,英文比较好的小伙伴可以直接看原文,我今天的内容是自己总结和部分翻译的结合物。
正篇
一、java中正则表达式相关优化
- 使用Matcher和Pattern进行预编译,替换String.matches, split, replaceAll, replaceFirst等方法,避免不必要的pattern编译。
二、java.util.LinkedList性能
- 考虑使用ArrayDeque用于基于队列的算法替换LinkedList,性能优于LinkedList;
- 使用ListIterator(forEach)遍历LinkedList【链表特性】;
- 避免任何接受或返回列表中元素索引的LinkedList方法【类似获取index的操作】,性能很差,遍历列表实现;
- 使用pollFirst/pollLast替换LinkedList.remove/removeFirst/removeLast方法。
三、java.util.Date, java.util.Calendar and java.text.SimpleDateFormat performance日期的存储,解析和转换
- 除非您必须使用java.util.Date,否则不要使用它。改用普通的long。
- java.util.Calendar可用于各种日期计算,但要避免存储大量此类对象或广泛创建它们——它们消耗了大量内存,创建成本高昂。
- java.text.SimpleDateFormat适用于一般案例日期时间解析,但如果您必须以相同的格式解析大量日期(特别是没有时间的日期),最好避免它。改为手动实现解析器。
四、使用Joda Time类库进行时间处理,在某些方面性能更好
五、java.io.ByteArrayOutputStream,不应该在性能关键代码中使用ByteArrayOutputStream
- 对于性能关键型代码,请尝试使用ByteBuffer而不是ByteArrayOutputStream。如果您仍然想使用ByteArrayOutputStream-请取消其同步。
- 在大多数情况下,避免使用ByteArrayOutputStream.toByteArray方法——它创建一个内部字节数组的副本。如果您的应用程序使用几千兆字节内存,收集这些副本的垃圾可能需要相当长的时间。
六、java.io.BufferedInputStream, java.util.zip.GZIPInputStream, java.nio.channels.FileChannel:这两个流中的一些小性能陷阱
- BufferedInputStream和GZIPInputStream都有内部缓冲区。前者的默认大小为8192字节,后者的默认大小为512字节。一般来说,值得将任何尺寸增加到至少65536。(减少BufferedInputStream,GZIPInputStream自动扩容的性能损耗)
七、各种通用压缩算法的性能——其中一些速度惊人(LZ4)
- 如果您认为数据压缩速度非常缓慢,请检查LZ4(快速)实现,该实现能够以约320 Mb/秒的速度压缩文本文件——对于大多数应用程序来说,这种速度的压缩不应该很明显。如果可能,将LZ4压缩缓冲区大小增加到32M限制是有意义的(请记住,您需要一个类似大小的缓冲区进行解压缩)。您还可以尝试将2个具有32M缓冲区大小的LZ4BlockOutputStream-s链起来,以充分利用LZ4。
- 如果您被限制使用第三方库或想要更好的压缩,请检查JDK deflate(lvl=1)【实现类:java.util.zip.DeflaterOutputStream / InflaterInputStream】编解码器——它能够以~75 Mb/秒的速度压缩同一文件。
八、ava.util.Map、java.util.Set及其大多数实现的优化(尽量避免使用contains)
- 对于集合,contains+add/remove调用对应替换为单个add/remove调用;
- 对于Map,避免contains+get使用,替换为get,然后是get结果的null检查。contains+remove对应替换为单个remove调用并检查其结果。【另:ConcurrentHashMap的containsKey方法本身就是get方法实现的】
九、单线程和多线程环境中的java.util.Random和java.util.concurrent.ThreadLocalRandom概述
- 在任何情况下,都不要在多个线程之间共享java.util.Random的实例,而是将其包装在ThreadLocal中。
十、使用Apache Commons StringUtils.replace而不是String.replace
- 如果代码中存在大量的替换操作,考虑使用StringUtils。StringUtils远远胜过了 Java 8 的 String.replace 方法。
// replace this
test.replace(“test”, “simple test”);
// with this
StringUtils.replace(test, “test”, “simple test”);
十一、使用double/long替换BigDecimal
-
尽可能使用较小的货币单位,比如(角,分),使用double或long保存;
之前在stackoverflow上看到有个老哥说BigDecimal比double慢了1000倍,没有实践过,总之BigDecimal性能差是不争的事实。
- 四舍五入截取小数位长度(在使用尽可能小的单位前提下);
- 避免double转换成BigDecimal,如果要转换使用String转换BigDecimal;
点赞收藏
分类: