- 浏览: 210324 次
最新评论
-
jin8000608172:
Profiler类是自己写的还是开源jar里面的,如果是开源j ...
isInfoEnabled究竟多有用? -
u011358822:
www.baidu.com
实战Concurrent -
u011358822:
[url][img][list][*]引用[/list][/i ...
实战Concurrent -
water_lang:
这本书我买了一本,但是我还是没找到该怎么解决事务这块,mong ...
《MongoDB实战》译者序 -
DREAM_UTOPIA:
每周推荐非常好,观点独到,涉及面广,谢谢
每周推荐阅读2013Q2汇总
前段时间,公司里组织了一次代码检查,其中有一条检查项让我有些费解:
理由是大量的不输出的日志对性能会有影响(日志中存在字符串拼接)。如果说只是DEBUG的加上,我也就认了,可是在系统中写成INFO的日志如果不输出,那还写它干嘛,我就是想看到关键路径的日志。而且在大多数日志上加上这么一个判断真的很难看。。。
所谓上有政策,下有对策,于是有人开始写一些包装了判断的辅助类,当中用这样的代码(截取):
public class LogUtil { public static void info(Logger logger, String message) { if (logger.isInfoEnabled()) { logger.info(message); } } public static void debug(Logger logger, String message) { if (logger.isDebugEnabled()) { logger.debug(message); } } public static void debug(Logger logger, String message, Throwable throwable) { if (logger.isDebugEnabled()) { logger.debug(message, throwable); } } }
但这样的代码真的就能解决问题了吗?答案是“不能”!字符串拼接还存在。
那让我们分两个部分来看一下这个问题:
- 日志中的字符串拼接真的对性能影响很大吗
- 加不加isInfoEnabled的性能差距究竟有多少
关于第一个问题,String的拼接是不修改原来的字符串的,而是创建一个新的String对象,道理上是这么说的,我们也该这么理解。但Java编译器并不傻,实际情况是怎么样的呢,它会做些优化。请看如下代码:
public class StringAddDemo { public static void main(String[] args) { String a = "abc"; String b = a + "def"; System.out.println(b + "ghi"); } }
在编译后,通过javap -c StringAddDemo看看结果:
public class StringAddDemo extends java.lang.Object{
public StringAddDemo();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2; //String abc
2: astore_1
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
14: ldc #6; //String def
16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/la
ng/String;
22: astore_2
23: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream;
26: new #3; //class java/lang/StringBuilder
29: dup
30: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
33: aload_2
34: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
37: ldc #9; //String ghi
39: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
45: invokevirtual #10; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
48: return
}
实际这里的拼接用的是StringBuilder.append。情况没想的这么糟糕,而且1000次字符串拼接的开销都比不上一次远程调用的开销大,与其想着从这里挤性能,还不如去优化远程调用和数据库访问。
第二点,同样用实验来做说明,这里对比了使用辅助类,使用isInfoEnabled判断和不使用判断的情况,日志级别为INFO,另外再加了使用辅助类,使用isDebugEnabled判断和不使用判断的情况,都是循环输出20万次,每次的拼接在最后都加了些运算:
public class LogDemo { private static final Logger logger = LoggerFactory.getLogger(LogDemo.class); public static void main(String[] args) { Profiler.start(); Profiler.enter("Ignore"); for (int i = 0; i < 200000; i++) { LogUtil.info(logger, "test" + "test" + i + i*2); } Profiler.release(); Profiler.enter("InfoUtil"); for (int i = 0; i < 200000; i++) { LogUtil.info(logger, "test1" + "test2" + i + i*2); } Profiler.release(); Profiler.enter("isInfoEnabled"); for (int i = 0; i < 200000; i++) { if (logger.isInfoEnabled()) { logger.info("test3" + "test4" + i + i*2); } } Profiler.release(); Profiler.enter("info"); for (int i = 0; i < 200000; i++) { logger.info("test5" + "test6" + i + i*2); } Profiler.release(); Profiler.enter("DebugUtil"); for (int i = 0; i < 200000; i++) { LogUtil.debug(logger, "test7" + "test8" + i + i*2); } Profiler.release(); Profiler.enter("isDebugEnabled"); for (int i = 0; i < 200000; i++) { if (logger.isDebugEnabled()) { logger.debug("test9" + "test0" + i + i*2); } } Profiler.release(); Profiler.enter("debug"); for (int i = 0; i < 200000; i++) { logger.debug("tes1" + "tes2" + i + i*2); } Profiler.release(); Profiler.release(); System.out.println(Profiler.dump()); } }
( 说明:这里的Profiler类是个工具类,作用是记录调用的时间;代码有截取;第一个循环主要是预热一下,不在统计范围内)
经过了几次测试,结果如下:
+---29,937 [14,187ms, 24%, 24%] - isInfoEnabled
+---44,124 [13,938ms, 24%, 24%] - info
+---58,062 [31ms, 0%, 0%] - DebugUtil
+---58,093 [16ms, 0%, 0%] - isDebugEnabled
`---58,109 [46ms, 0%, 0%] - debug
+---14,968 [14,656ms, 25%, 25%] - InfoUtil
+---29,624 [14,141ms, 24%, 24%] - isInfoEnabled
+---43,765 [14,265ms, 25%, 25%] - info
+---58,030 [47ms, 0%, 0%] - DebugUtil
+---58,077 [0ms] - isDebugEnabled
`---58,077 [47ms, 0%, 0%] - debug
+---14,999 [14,922ms, 26%, 26%] - InfoUtil
+---29,921 [14,093ms, 24%, 24%] - isInfoEnabled
+---44,014 [14,219ms, 24%, 24%] - info
+---58,233 [47ms, 0%, 0%] - DebugUtil
+---58,280 [0ms] - isDebugEnabled
`---58,280 [47ms, 0%, 0%] - debug
+---14,656 [14,812ms, 26%, 26%] - InfoUtil
+---29,468 [14,344ms, 25%, 25%] - isInfoEnabled
+---43,812 [13,890ms, 24%, 24%] - info
+---57,702 [31ms, 0%, 0%] - DebugUtil
+---57,733 [16ms, 0%, 0%] - isDebugEnabled
`---57,749 [47ms, 0%, 0%] - debug
+---16,219 [16,719ms, 25%, 25%] - InfoUtil
+---32,938 [17,703ms, 27%, 27%] - isInfoEnabled
+---50,641 [15,157ms, 23%, 23%] - info
+---65,798 [47ms, 0%, 0%] - DebugUtil
+---65,845 [0ms] - isDebugEnabled
`---65,845 [47ms, 0%, 0%] - debug
(数据说明:第一列为开始计时的时间点,[]内为时间及统计,15,171ms为该阶段的具体耗时,后面的百分比是该阶段耗时在这个统计内所占的百分比)
对上述数据分析后,可以得到这样的结论:
- 日志输出前的判断确实有效,但效果甚微
- 在日志级别较低,不会输出的情况下,日志的耗时基本可以忽略 ,20万次的调用耗时在50ms内
- 在日志级别满足输出要求时,3种方法差别不大
针对第3条再做些补充说明,日志输出大的开销应该在IO上,计算应该不会很多,也不该很多,如果存在大量的运算请自己考虑下是不是有问题;既然是确认要输出的日志,那增加判断其实是种浪费,虽然这种判断的开销可以忽略。
综上所述,个人建议在日常系统中无需对日志增加isInfoEnabled判断,想通过这种处理来优化效果的作用不会很明显,还是把精力从日志移到数据库和远程调用上效果更好些。 (特殊情况下,如果在日志中有复杂的操作,可以酌情考虑,但个人不倾向于复杂的日志)
评论
完全可以啊。关键看你怎么拦截。
能给个例子看看吗?另外,还好看么?
是的,我也同意,不加这个判断,对代码的可读性很有好处,文章中我也说了,加这个很难看。
关于Log4j里是否默认有这个判断,不是每个系统都能用新版本,而且日志实现很多,也不一定直接用Log4j,比如我们在项目里用的就是公司自己封装过的。
反正我现在已经放弃了这种检查了,因为实在太难看了,影响代码阅读,性能就将就一下吧。
用AOP的方式就不难看了。
AOP可以精细到某一行代码前后了吗?仅仅是函数级别没有什么意义。
完全可以啊。关键看你怎么拦截。
是的,我也同意,不加这个判断,对代码的可读性很有好处,文章中我也说了,加这个很难看。
关于Log4j里是否默认有这个判断,不是每个系统都能用新版本,而且日志实现很多,也不一定直接用Log4j,比如我们在项目里用的就是公司自己封装过的。
反正我现在已经放弃了这种检查了,因为实在太难看了,影响代码阅读,性能就将就一下吧。
用AOP的方式就不难看了。
AOP可以精细到某一行代码前后了吗?仅仅是函数级别没有什么意义。
是的,我也同意,不加这个判断,对代码的可读性很有好处,文章中我也说了,加这个很难看。
关于Log4j里是否默认有这个判断,不是每个系统都能用新版本,而且日志实现很多,也不一定直接用Log4j,比如我们在项目里用的就是公司自己封装过的。
反正我现在已经放弃了这种检查了,因为实在太难看了,影响代码阅读,性能就将就一下吧。
用AOP的方式就不难看了。
是的,我也同意,不加这个判断,对代码的可读性很有好处,文章中我也说了,加这个很难看。
关于Log4j里是否默认有这个判断,不是每个系统都能用新版本,而且日志实现很多,也不一定直接用Log4j,比如我们在项目里用的就是公司自己封装过的。
反正我现在已经放弃了这种检查了,因为实在太难看了,影响代码阅读,性能就将就一下吧。
public void debug(Object message) { if(repository.isDisabled(Level.DEBUG_INT)) return; ...
在 Log4j 1.2.15中,其实源代码中已经判断是否开放了debug等权限。
还有一点,楼主可能没有注意,在低版本的实现中,可能没有加这个类似的判断,并且可读性更好。
是的,我也同意,不加这个判断,对代码的可读性很有好处,文章中我也说了,加这个很难看。
关于Log4j里是否默认有这个判断,不是每个系统都能用新版本,而且日志实现很多,也不一定直接用Log4j,比如我们在项目里用的就是公司自己封装过的。
public void debug(Object message) { if(repository.isDisabled(Level.DEBUG_INT)) return; ...
在 Log4j 1.2.15中,其实源代码中已经判断是否开放了debug等权限。
还有一点,楼主可能没有注意,在低版本的实现中,可能没有加这个类似的判断,并且可读性更好。
发表评论
-
那些你该了解的Spring子项目
2013-03-20 14:39 1423去年年底,Spring Framework正式发布了3.2G ... -
《实战HotSpot JVM GC》分享Slides
2012-06-22 12:09 1720前阵子在QClub上海站做了一个与JVM GC优化相关的分享, ... -
如何简单模拟Web服务
2011-03-21 18:57 2176在SOA环境中,系统不可 ... -
代码中的坏味道
2011-01-07 04:09 1367最近InfoQ上连载了郑烨 ... -
一个关于基于注解的Spring MVC的简单介绍
2009-05-26 17:52 2854前段时间给同事们做了一个关于Spring MVC的分享,简单介 ... -
实战Concurrent
2009-04-08 13:51 3897编写多线程的程序一直都是一件比较麻烦的事情,要考虑很多事情,处 ... -
关于表单防重复提交一些东东
2009-03-13 22:27 2330前阵子弄了些表单防重复提交的东西,想整理整理,免得下次要用时再 ... -
Eclipse对JDK说“不”了
2008-09-30 21:21 1957最近开始翻译Spring Recipes了,既然是讲Sprin ... -
自己写的第一段AOP代码。
2005-04-13 22:36 1573代码1:使用安全的rand() ... -
FIFO、LRU、OPT的三个简单实现
2005-04-28 16:11 31921.利用随机数产生一个指令序列,共320条指令。其地址按下述原 ... -
JMeter小实验——JSP性能简单测试
2006-04-17 16:56 2448首先要做的当然是到Apache的站点下在一个最 ... -
利用缓存提高小型站点性能
2006-04-23 16:11 1216最近结束了 ... -
都是JDBC-ODBC惹得祸
2006-09-23 11:23 1166前阵子的一个项目需要 ... -
Fedora下瞎折腾了一个半小时,还是Sun的虚拟机可靠
2007-03-23 22:00 1195今天早上跑去了网络学院做技术支持, 他们碰到的问题是一个web ... -
一个泛型Hibernate DAO实现
2007-08-06 11:58 1721自己四处参考,写写抄抄折腾出来的一个泛型Hibernate D ... -
自己出的几道关于Spring和Hibernate的面试题
2008-02-29 16:49 2483很简单的题目,随便出着玩的,如果你是高手就请直接跳过,若有雷同 ... -
Spring MVC快速上手教程
2008-04-01 22:00 3056Spring Framework可以被使用在很多场合之中,考虑 ... -
一些关于Liferay的使用心得
2008-01-07 15:58 2141Liferay是一个出色的Java开源Portal产品,其中整 ...
相关推荐
起点小说解锁.js
299-煤炭大数据智能分析解决方案.pptx
299-教育行业信息化与数据平台建设分享.pptx
网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes
时间复杂度是计算机科学中用来评估算法效率的一个重要指标。它表示了算法执行时间随输入数据规模增长而变化的趋势。当我们比较不同算法的时间复杂度时,实际上是在比较它们在不同输入规模下的执行效率。 时间复杂度通常用大O符号来表示,它描述了算法执行时间上限的增长率。例如,O(n)表示算法执行时间与输入数据规模n呈线性关系,而O(n^2)则表示算法执行时间与n的平方成正比。当n增大时,O(n^2)算法的执行时间会比O(n)算法增长得更快。 在比较时间复杂度时,我们主要关注复杂度的增长趋势,而不是具体的执行时间。这是因为不同计算机硬件、操作系统和编译器等因素都会影响算法的实际执行时间,而时间复杂度则提供了一个与具体实现无关的评估标准。 一般来说,时间复杂度越低,算法的执行效率就越高。因此,在设计和选择算法时,我们通常希望找到时间复杂度尽可能低的方案。例如,在排序算法中,冒泡排序的时间复杂度为O(n^2),而快速排序的时间复杂度在平均情况下为O(nlogn),因此在处理大规模数据时,快速排序通常比冒泡排序更高效。 总之,时间复杂度是评估算法效率的重要工具,它帮助我们了解算法在不同输入规模下的性
5G通信行业、网络优化、通信工程建设资料
网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
5G通信行业、网络优化、通信工程建设资料
《基于小程序的交友系统的设计与实现》是一个融合了小程序技术和社交功能的毕业设计项目。该项目旨在通过开发一款小程序,为用户提供一个便捷、有趣的交友平台,满足用户寻找新朋友、拓展社交圈的需求。 一、项目背景与目标 随着移动互联网的普及,小程序以其轻便、易用的特性受到了广大用户的喜爱。本项目旨在利用小程序技术开发一款交友系统,通过简洁明了的界面设计和丰富多样的社交功能,吸引用户参与并提升用户体验。通过实现这一系统,旨在帮助用户拓展社交圈,增进人际关系,并推动社交领域的创新与发展。 二、系统设计与功能实现 用户注册与登录:系统提供用户注册与登录功能,确保用户信息的真实性和安全性。用户可以通过手机号或第三方社交账号进行注册和登录。 个人资料展示:用户可以在个人资料页面展示自己的基本信息、兴趣爱好、照片等,以便其他用户了解并产生互动。 附近的人:系统通过定位功能展示附近的其他用户,用户可以浏览附近的人的信息,并主动发起聊天或交友请求。 聊天功能:系统提供一对一的聊天功能,用户可以与感兴趣的人进行实时交流,增进彼此的了解。 活动组织:用户可以发起或参与各类线下活动,如聚会、运动、旅行
5G通信行业、网络优化、通信工程建设资料
shampoo-sales.csv
59-《煤矿测量规程(1989版)》150.pdf
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
5G通信行业、网络优化、通信工程建设资料。
AXIS T864 系列多通道 AXIS T8646 PoE+ 同轴电缆刀片套件 AXIS T8648 PoE+ 同轴电缆刀片紧凑型套件安装指南
MATLAB学习个人笔记总结.7z
【资源说明】【毕业设计】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。 2、适用人群:主要针对计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、数学、电子信息等)的同学或企业员工下载使用,具有较高的学习借鉴价值。 3、不仅适合小白学习实战练习,也可作为大作业、课程设计、毕设项目、初期项目立项演示等,欢迎下载,互相学习,共同进步!
5G通信、网络优化与通信建设