私人MEMO--性能调优 包括JVM常用调优和系统调优

本文是我的私人Memo,仅仅是大纲备忘作用。一段时间后我会整理好。


JVM调优

    主要是内存方向的调优 各个代的大小,GC策略等等。(GC会导致应用线程挂起 严重影响性能 降低GC导致的应用暂停时间很有必要)
    JVM内存 = 新生代+老年代+持久代(方法区)
    -Xms :初始JVM内存大小
    -Xmx :最大JVM内存大小 这俩一般一样 避免运行期间内存变大
    -Xmn :年轻代内存大小 (一般为Xmx的1/3)
           年轻代包括Eden和两个Survivor区 默认8:2 80% 10% 10%
    -XX:SurvivorRatio=X 修改Eden和Survior的大小比例
    老年代的大小无法设置,等于JVM内存-年轻代-持久代 如果没有-Xmn参数 可以通过-XX:NewRatio=X设置年轻代与老年代的比例 默认1:2
    -XX:PermSize=256M:持久代初始内存大小
    -XX:MaxPermSize=512M:最大持久代内存大小
    -Xss:每个线程的堆栈大小
    -XX:MaxTenuringThreshold :设置新生代存活周期
    比如java -Xmx3550m -Xms3550m -Xmn2g -Xss128k   (jstat分析GC状况)

    避免新生代大小太小导致minor GC频繁 并且可能导致minor gc 对象直接进入老年代
    避免新生代设置过大导致老年代变小,使得Full GC频繁 并且minor GC耗时大幅度增加 新生代一般是JVM内存的1/3左右
    避免Survivor过大或者过小
    合理设置新生代存活周期 -XX:MaxTenuringThreshold 默认值15

系统调优
    CPU消耗严重的解决办法
    1、执行线程没有任何挂起动作,一旦执行导致CPU没有机会调度其他线程 造成线程饿死。Thread.sleep()释放CPU使用权(不释放锁) 给其他线程执行机会
       这样导致单次执行性能降低,但是由于降低CPU消耗,反而提高了总体的平均性能。
    2、线程过多导致线程之间切换次数太多,或者锁竞争激烈。最简单的解决办法就是减少线程数的同时增加一个缓冲队列(因此不是线程数越多吞吐量越高)。
       另外可以进行锁优化,协程来支撑更高的并发量。
       当前JDK创建一个Thread对象意味着运行了一个原生线程,当这个线程有任何阻塞动作,这个线程就会被挂起,但是依然占据线程资源。
       阻塞动作完成,OS恢复线程的上下文,调度执行。
    文件IO消耗严重的解决办法
        造成文件IO消耗严重主要因为多个线程写大量数据到同一文件,导致写入越来越慢,锁抢占激烈。
    1、异步写文件,将写文件的动作改为异步(比如日志log4j的AsyncAppender)
    2、批量读写,频繁的读写操作对IO消耗很严重,批量操作可以提高性能。
    3、限流,将文件IO消耗控制在一个可接受范围。
    4、限制文件大小。
    网络IO消耗严重的解决方法
    1、限流,限制packet发送频率
    内存消耗严重的解决办法:
    1、释放不必要的引用。一个很典型的例子是线程复用情况下使用ThreadLocal导致其中存放对象一直不会被GC
    2、使用对象缓存池。一定程度上可以降低JVM堆内存的使用,大幅提升性能。
    3、合理控制缓存池大小,采用合理的缓存失效算法。太多对象在缓存池反而会造成内存严重消耗,Full GC增多。
    4、合理使用SoftReference和WeakReference来进行缓存。SoftReference在内存不够会回收,WeakReference在Full GC回收。
    资源消耗不多,但是程序执行慢的解决办法
        一般是锁竞争激烈以及未充分发挥硬件资源
    1、锁优化 采用下面的方法:
        a、采用并发包中的类。这里面许多采用了lock-free、nonblocking算法,减少锁竞争。
        b、Treiber算法 用于实现无阻塞Stack 采用了AtomicReference基于CAS实现。
        c、Michael-Scott非阻塞队列算法 基于CAS和AtomicReference实现队列非阻塞操作。比如J.U.C中的ConcurrentLinkedQueue
        d、减少锁的使用
        e、拆分锁 独占锁拆为多把锁,如ConcurrentHashMap默认拆分为16把锁,提高读写速度。(当然这会导致CPU消耗增加)
        f、考虑某些特殊锁的适用场景 比如CopyOnWrite的实现方式,很适合读多写少。
    2、未充分使用硬件资源
        a、CPU未充分使用 可以考虑适当增加线程个数(毕竟多核CPU越来越多)
        b、内存未充分使用 适当增加缓存
发布了106 篇原创文章 · 获赞 285 · 访问量 59万+

猜你喜欢

转载自blog.csdn.net/qq_35580883/article/details/79282322