上周没事扫扫系统原来的代码,突然发现这样一段代码:
if(log.isInfoEnable())
{
log.info("ID"+userID+"pwd"+userPwd);
}
因为之前写的日志类都是公司内部自己的日志类,对log4j用的并不多。当时看了这段代码觉得很奇怪,代码意思我是明白的,log本身就可以根据打印权限,判断当前是否打印呀,为什么专门要加上这样一条判断呢?后来查了一下,发现是由于性能方面考虑的。
如果直接写入这样一段话
log.info("ID"+userID+"pwd"+userPwd);
当打印等级为“info”之上时,系统并不会智能的跳过这句话,而是会进这句话的内部,那么进去之前第一件事,必定就是计算参数。
那么这里就会拼接字符串了。
一般来说,日志的打印等级越低,打印的内容就越详细(越趋于调试和跟踪代码),这时出现字符串拼接或者参数计算的东西就会越来越多,也就越耗费性能。此时如果我们设定当前的打印等级非常高,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )如ERROR等级,那么debug和info 级别的日志就不会打印,但是由于debug和info的打印语句非常多,组装参数所耗费的性能也就非常大,所以我们这时候把判断能否打印的语句放在外边先进行判断,虽然乍一看会觉得多此一举,其实当debug和info的日志越多时,越能节约无谓的性能开销。
很多网上很多人说这里不能为了代码的易读性而使用封装,因为在调用封装的方法时,其实已经开始计算参数了,反而显得很可笑,如下:
public void info(String msg)//当前msg其实已经是拼接后的字符串了
{
if(log.isInfoEnable())
{
log.info("ID"+userID+"pwd"+userPwd);
}
}
总结后的反思
1:很多人觉得,不封装就会破坏代码的易读性,很难看,如果封装了,又会起到反效果,所以压根就不要节约这点性能好了,将时间和精力放置在数据库连接查询,数据加载排序等等这些更耗费性能的事情上,其实我也是赞同的,我觉得做性能优化就要一层层的做,没必要从一开始就扣住所有细节,当然遵守一定的编码制度是很好的。但是倘若一开始就从所有 细节(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )着手,反而会影响其它重要的大的优化点。
2:对于这种写法上我个人想了一下觉得如下的写法既能保证代码的可读性,也能体现出这种判断的性能优势,但是会多出一个创建数组的性能开销
1 public void info(String... args)//使用可变参数
2 {
3 if(log.isInfoEnabled())
4 {
5 StringBuilder sb=new StringBuilder();
6 for (int i = 0; i < args.length; i++)
7 {
8 sb.append(args[i]);
9 }
10 log.info(sb.toString());
11 }
12 }
13 }