性能优化课堂笔记和培训心得_培训心得和评课反馈表

学习培训心得体会 时间:2020-02-28 20:29:54 收藏本文下载本文
【www.daodoc.com - 学习培训心得体会】

性能优化课堂笔记和培训心得由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“培训心得和评课反馈表”。

软件性能优化心得体会

随着企业级开发平台诸如J2EE的普及和发展,越来越多的企业应用采用了这些技术作为快速开发平台,但是,这些应用也面临着一些困扰,特别是性能问题。这主要是由这些系统的分布性、复杂性和数据无关性引起的。高性能是软件高质量的重要体现,也是用户满意度提高的重要软件特征,为了提高软件的性能,在这次培训中,老师从以下几个层次讨论软件性能优化。

一、Java底层代码的性能优化

1、首先根据Jvm虚拟机的内存机制来优化系统

堆(Heap)是一个复杂的结构,对象及其成员通常保存在堆中。运行时在数据区, 动态创建,堆中的内容由 GC 负责回收。栈(Stack)是一个简单的结构,方法的参数(基本型别的值、指向对象的引用)通常保存在栈中。栈中的内容在方法执行完时就被回收了。

栈的存取速度比堆要快,栈数据可以共享,存在栈中的数据大小与生存期必须是确定的,栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。

使用局部变量的好处在于作用范围是变量定义的方法内部,一旦离开作用域,栈内存将被快速释放,与GC无关,而其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢,但是可以自动回收。所以要尽量使用局部变量。在这里,培训的老师举了个人例子 A for(int i=0;i

Object o = new Object();} B Object o = null;for(int i=0;i

o = new Object();} A和B之间究竟哪个性能更加好呢?

在这里A和B的唯一区别在于,B在循环体外定义Object,而A是在循环体内定义Object,显然A的Object作用域是在局部,一旦执行下一轮循环,立即释放原先定义的Object,而B的Object作用域是在全局,必须等到循环全部结束,Object才能被释放,因此A的性能要好于B,而且两者运行速度不是一个数量级。

2、需要慎用异常处理机制

因为异常只能用于错误处理,不适合用来控制流程,抛出异常的同时,系统往往会创建一个新的对象,只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。这样对系统的性能会造成一定的影响,因此,要尽量少用自定义的异常抛出机制。

3、使用多线程会提高系统的性能,但是处理多线程的时候,为了防止资源竞争,需要加锁。

一般锁是Synchronized,jdk 1.5 版本多加了个ReetrantLock,我查阅了官方说明:重入锁(ReentrantLock)是一种递归无阻塞的同步机制,它可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大。ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有。当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁定并返回。如果当前线程已经拥有该锁定,此方法将立即返回。可以使用 isHeldByCurrentThread()和 getHoldCount()方法来检查此情况是否发生。

虽然 ReentrantLock 是个非常动人的实现,相对 synchronized 来说,它有一些重要的优势,但是我认为急于把 synchronized 视若敝屣,绝对是个严重的错误。java.util.concurrent.lock 中的锁定类是用于高级用户和高级情况的工具。一般来说,除非对 Lock 的某个高级特性有明确的需要,或者有明确的证据(而不是仅仅是怀疑)表明在特定情况下,同步已经成为可伸缩性的瓶颈,否则还是应当继续使用 synchronized。

为什么在一个显然“更好的”实现的使用上主张保守呢?因为对于 java.util.concurrent.lock 中的锁定类来说,synchronized 仍然有一些优势。比如,在使用 synchronized 的时候,不能忘记释放锁;在退出 synchronized 块时,JVM 会为你做这件事。很容易忘记用 finally 块释放锁,这对程序非常有害。你的程序能够通过测试,但会在实际工作中出现死锁,那时会很难指出原因(这也是为什么根本不让初级开发人员使用 Lock 的一个好理由。)

另一个原因是因为,当 JVM 用 synchronized 管理锁定请求和释放时,JVM 在生成线程转储时能够包括锁定信息。这些对调试非常有价值,因为它们能标识死锁或者其他异常行为的来源。Lock 类只是普通的类,JVM 不知道具体哪个线程拥有 Lock 对象。而且,几乎每个开发人员都熟悉 synchronized,它可以在 JVM 的所有版本中工作。在 JDK 5.0 成为标准(从现在开始可能需要两年)之前,使用 Lock 类将意味着要利用的特性不是每个 JVM 都有的,而且不是每个开发人员都熟悉的。

既然如此,我们什么时候才应该使用 ReentrantLock 呢?答案非常简单 —— 在确实需要一些 synchronized 所没有的特性的时候,比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。ReentrantLock 还具有可伸缩性的好处,应当在高度争用的情况下使用它,但是请记住,大多数 synchronized 块几乎从来没有出现过争用,所以可以把高度争用放在一边。我建议用 synchronized 开发,直到确实证明 synchronized 不合适,而不要仅仅是假设如果使用 ReentrantLock “性能会更好”。请记住,这些是供高级用户使用的高级工具。(而且,真正的高级用户喜欢选择能够找到的最简单工具,直到他们认为简单的工具不适用为止。)。一如既往,首先要把事情做好,然后再考虑是不是有必要做得更快。

4、线程池

创建和销毁线程是非常耗资源的,当服务器同时接受很多请求时,根据操作系统和内存容量,可以创建的线程是有限的,因此需要容易造成内存泄漏,产生异常。因此我们采用线程池技术,Executor创建一个可根据需要创建新线程的线程池,以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。例,创建20个线程大小的线程池:Executors.newFixedThreadPool(20);

5、原子并发

Hashtable(或者替代方案 Collections.synchronizedMap)的可伸缩性的主要障碍是它使用了一个 map 范围(map-wide)的锁,为了保证插入、删除或者检索操作的完整性必须保持这样一个锁,而且有时候甚至还要为了保证迭代遍历操作的完整性保持这样一个锁。这样一来,只要锁被保持,就从根本上阻止了其他线程访问 Map,即使处理器有空闲也不能访问,这样大大地限制了并发性

6、ConcurrentHashMap摒弃了单一的 map 范围的锁,取而代之的是由 32 个锁组成的集合,其中每个锁负责保护 hash bucket 的一个子集。锁主要由变化性操作(put()和 remove())使用。具有 32 个独立的锁意味着最多可以有 32 个线程可以同时修改 map。绝大多数系统应用绝对够用。并发有32个锁,超过了32个锁就会处于等待状态。ConcurrentLinkedQueue也具有类似的原理。

7、对于对象的操作New, clone, reflection之间的比较

对象生成效率:new一个对象生成的效率高于深clone,深clone效率高于反射 复杂对象(带有数据结构参数,如Map,List),浅clone对象生成的效率高于new一个对象,new一个对象效率高于反射

采用深clone和浅clone效率高,而采用Reflection效率低,因此我们平时编写代码时要尽量少用反射。

8、字符串优化

采用字符串打印out.println()会影响效率,因此需要减少字符串打印 多使用StringBuffer,避免多字符串级联

二、数据库的性能优化

1、对数据库系统进行设置,方便优化,以db2为例,使用 DB2 的自动功能,尤其是 DB2 9 支持的 STMM,以及 DB2 Version 8 和 DB2 9 都支持的 Automatic Maintenance(尤其是自动的 runstats)。这些功能不但会减少监控和维护数据库所需的操作,也能对数据库进行更加有效的调优。

2、死锁检测以及提高锁的并发性能的方法

数据的锁定分为两种方法,第一种叫做悲观锁,第二种叫做乐观锁。什么叫悲观锁呢,悲观锁顾名思义,就是对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住。而乐观锁就是认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让用户返回错误的信息,让用户决定如何去做

在DB2等很多数据库中,数据的锁定通常采用页级锁的方式,也就是说对一张表内的数据是一种串行化的更新插入机制,在任何时间同一张表只会插1条数据,别的想插入的数据要等到这一条数据插完以后才能依次插入。带来的后果就是性能的降低,在多用户并发访问的时候,当对一张表进行频繁操作时,会发现响应效率很低,数据库经常处于一种假死状态。而Oracle用的是行级锁,只是对想锁定的数据才进行锁定,其余的数据不相干,所以在对Oracle表中并发插数据的时候,基本上不会有任何影响。

在数据库中可以通过改变锁来提高应用程序并发性能。DB2检测死锁采用如下方法

首先建立一个死锁事件监控器db2 connect to sample db2 “create event monitor dlmon for tables, deadlocks with details write to file 'C:dlmon'” mkdir C:dlmon db2 “set event monitor dlmon state 1” 其次等待死锁,第三通过 db2evmon 工具可以获得死锁信息的日志,并且把日志文件导入到本地机器的文件系统当中。在下面一节,我们将详细分析导出的日志文件。db2 connect reset db2evmon-path c:dlmon > c:dlmondllog1.txt Db2结束引起死锁的应用采用如下3种方法:(1)、SELECT AGENT_ID_HOLDING_LK, LOCK_MODE, TABNAME, AGENT_ID FROM SYSIBMADM.LOCKWAITS查找死锁

(2)根据AGENT_ID查出应用程序db2 list application show detail(3)结束引发死锁的应用db2 “force application(id)”

3、sql语句的优化

(1)使用索引来可以更快地遍历表,提高系统速度,但索引不能过量添加,会增加数据库的极大开销。有时候索引不一定能带来速度快,比如用到in,or子句对索引没用处。(2)采用NOT IN会多次扫描表,建议使用EXIST,NOT EXIST,IN,LEFT OUTER JOIN(3)EXISTS要远比IN的效率高。里面关系到full table scan和range scan。几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。

(4)在海量查询时尽量少用格式转换,比如把字符型转换成数字型。

(5)慎用游标。在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,这样可使性能得到明显提高。对于一些多表操作,少用游标,在oracle中用临时表比用索引要快,但是在其他操作系统中不一定。

(6)不用“”或者“!=”操作符。对不等于操作符的处理会造成全表扫描,可以用“”代替

(7)Where子句中出现IS NULL或者IS NOT NULL时,Oracle会停止使用索引而执行全表扫描。可以考虑在设计表时,对索引列设置为NOT NULL(8)当通配符“%”或者“_”作为查询字符串的第一个字符时,索引不会被使用。

(9)Order By语句中的非索引列会降低性能,可以通过添加索引的方式处理。严格控制在Order By语句中使用表达式

三、应用服务器的优化

1、对应用服务器的连接池优化,连接池的增长速度等

2、Web线程等待队列一般情况下应该为0.页面提交的线程请求

weblogic并发的锁机制好,所以访问的速度快。比WebSphere和tomcat都要速度快。

四、表示层的优化

1、html的标记压缩,采用gzip工具压缩

2、尽量采用div来代替table,嵌套table很影响render性能。

五、优化工具的使用 P6Spy & IronTrackSQL SqlDbxPersonal JProfiler HttpAnalyzerFullV4 Fiddler2

通过这次的培训活动,我有了如下收获和体会:

1、开阔了视野,了解了很多新的知识。了解了oracle和db2的差异之处,这是我过去一直想要知道的。

2、在编程技巧方面,学习到了以往都没有注意过得,特别是jvm最底层的性能优化,对我以后应用jfw框架技术处理业务逻辑提供了很好的借鉴。因为框架对底层代码进行了一系列的封装,采用内存堆栈和并发锁的观点去编程,可以减少很多不必要的对系统的开销。

3、拥有了更多的方法和手段来优化系统,在软件的各个层面上都需要做处理来优化系统,或许在某个细节处做处理效果并不突出,但是在各个层面的综合作用下,性能提高会非常明显。

4、学习了性能优化工具,以后开发程序多使用辅助工具,能真正提高效率。

5、因为参加了这次培训,我查阅了很多相关资料,还了解到了很多培训中没有提到内容,更加充实了知识。

6、软件技术的日新月异也促使我要不断更新自己的知识结构,为应对不同体系结构的软件分析与设计做好准备。

下载性能优化课堂笔记和培训心得word格式文档
下载性能优化课堂笔记和培训心得.doc
将本文档下载到自己电脑,方便修改和收藏。
点此处下载文档

文档为doc格式

    热门文章
      整站推荐
        点击下载本文