性能优化一点总结
个人管理方面
1、形成体系化的思想。
当做一件事(开发一个系统、解决一个问题)的时候,可以按照一定的体系去下手,这个体系可以理解为思维意识。少了很多无从下手、从零开始的过程,从而提升效率。这一点事需要个人长久的总结和丰富的经验!
2、开阔自己的视野。
从不同方面去寻找自己解决问题的思路,增加自己的选择空间,会让你权衡更全面,分析更透彻,从而理解更深入,解决问题也更到位。做技术,不能只看技术!一个技术大牛,多少都会对历史,对艺术有一些了解。
技术方面
1、代码
很多技术人员拿到一个性能优化的需求以后,都会向缓存、分库分表、异步、多线程、JVM优化等方向去思考。其实,很多时候应该从代码入手。代码优化的点很多很多,举几个例子:
1、当已经知道list大小的时候,直接指定list大小,可以有效避免list默认大小不够,而进行复制扩容。2、变量声明的位置能局部不全局,可以有效避免长久占用内存而不能被GC回收。3、for循环里大量声明变量,以致于消耗内存。等等吧
所以,要多加注意代码层面的优化,优化的空间很大,很可能代码优化之后就能满足性能要求,而不必增加设备来支持访问量!
2、SQL优化
SQL优化,个人认为可以从五个层面入手。
SQL语句优化 关键字的使用like、join、in、existSQL索引优化 索引的创建、索引的大小设置SQL引擎优化 根据业务需求,选择最适合的引擎数据库设计优化 我个人认知,主要是范式的设计。可以适当冗余数据,以减少数据库操作。*数据库连接池优化 连接池监控数、连接池方案的选择(这一块个人没使用过)
3、缓存优化
缓存在一个系统里或多或少都会涉及的。至于什么数据放入缓存,放入一个什么样的缓存,都是值得仔细斟酌的。 使用缓存的情况,个人感觉有两种:
短时间内相同数据重复查询多次且数据更新不频繁,这个时候可以选择先从缓存查询,查询不到再从数据库加载并回设到缓存的方式。高并发查询热点数据,后端数据库不堪重负。
选型考虑:
如果数据量小,并且不会频繁地增长又清空(这会导致频繁地垃圾回收),那么可以选择本地缓存。具体的话,如果需要一些策略的支持(比如缓存满的逐出策略),可以考虑Ehcache;如不需要,可以考虑HashMap;如需要考虑多线程并发的场景,可以考虑ConcurentHashMap。目前从资源的投入度、可运维性、是否能动态扩容以及配套设施来考虑,我们优先考虑Tair。除非目前Tair还不能支持的场合(比如分布式锁、Hash类型的value),我们考虑用Redis。
当然,使用缓存后,会面临很多问题,最大的一个问题就是数据一致性。这些就可以根据业务需要而制定不同的方案。
4、多线程
在一个系统里,在一定情况下使用多线程可以加快响应时间,比如一些异步任务,启动多线程去处理就好了,还有一些离线任务也不需要等待完成再返回等等。但是线上对响应时间要求较高的场合,尽量少用多线程,尤其是服务线程需要等待任务线程的场合(很多重大事故就是和这个息息相关),如果一定要用,可以对服务线程设置一个最大等待时间。
使用多线程又带来另一个问题,就是代码的复杂性。所以,建议如果单机单线程能够满足业务需求的尽量使用单机单线程,如果满足不了,则可以使用单机多线程,如果依然不能满足,再考虑多机多线程。
使用多线程时,可以考虑使用线程池,线程池的优点有两个:
1、提高性能,节省线程创建和销毁的开销,节省资源。2、可以利用线程池完成一些功能,比如限流。可以保障机器极限压力下的稳定处理能力。
5、JVM调优
JVM是Java WEB项目的基石,可以根据项目特点进行JVM调优。我所了解到的,只是调整一些GC回收机制和回收策略。比如新生代与老生代比值、eden与survivor比值、触发cms回收的old区比率阈值等。比如把大对象放入老年代等等。
当然,调优的路上很远也很长。包括技术的选型,监控的使用,软件的使用甚至硬件的使用。今天简单说这么多!
更多精彩内容,欢迎关注微信公众号:Java小笔记(ijavanote)