标签:soc aec hql sleep 共享资源 hashmap code nim 正在执行
改善性能意味着用更少的资源做更多的事情。为了利用并发来提高系统性能,我们需要更有效的利用现有的处理器资源,这意味着我们期望使 CPU 尽可能出于忙碌状态(当然,并不是让 CPU 周期出于应付无用计算,而是让 CPU 做有用的事情而忙)。如果程序受限于当前的 CPU 计算能力,那么我们通过增加更多的处理器或者通过集群就能提高总的性能。总的来说,性能提高,需要且仅需要解决当前的受限资源,当前受限资源可能是:
如果你的系统有如下的特点,说明系统存在性能瓶颈:
随着系统逐步增加压力,CPU 使用率无法趋近 100%(如下图)
持续运行缓慢。时常发现应用程序运行缓慢。通过改变环境因子(负载,连接数等)也无法有效提升整体响应时间
一个好的程序,应该是能够充分利用 CPU 的。如果一个程序在单 CPU 的机器上无论多大压力都不能使 CPU 使用率接近 100%,说明这个程序设计有问题。一个系统的性能瓶颈分析过程大致如下:
高性能在不同的应用场合下,有不同的含义:
性能调优的终极目标是:系统的 CPU 利用率接近 100%,如果 CPU 没有被充分利用,那么有如下几个可能:
下面是一种常见的错误
两个不相干的方法(没有使用同一个共享变量),共用了 this 锁,导致人为的资源竞争上面的代码将 synchronized 加在类的每一个方法上面,违背了保护什么锁什么的原则。对于无共享资源的方法,使用了同一个锁,人为造成了不必要的等待。Java 缺省提供了 this 锁,这样很多人喜欢直接在方法上使用 synchronized 加锁,很多情况下这样做是不恰当的,如果不考虑清楚就这样做,很容易造成锁粒度过大:
上面的代码应该变成下面
单 CPU 场合 将耗时操作拿到同步块之外,有的情况下可以提升性能,有的场合则不能:上面的代码,会导致一个线程长时间占有锁,而在这么长的时间里其他线程只能等待,这种写法在不同的场合下有不同的提升余地:
不管如何,缩小同步范围,对系统没有任何不好的影响,大多数情况下,会带来性能的提升,所以一定要缩小同步范围,因此上面的代码应该改为
上面提到的这些原因形成的性能瓶颈,都可以通过线程堆栈分析,找到根本原因。
性能瓶颈的几个特征:
鉴于性能瓶颈的以上特点,进行性能模拟的时候,一定要使用比系统当前稍高的压力下进行模拟,否则性能瓶颈不会出现。具体步骤如下:
通过线程堆栈,可以很容易的识别多线程场合下高负载的时候才会出现的性能瓶颈。一旦一个系统出现性能瓶颈,最重要的就是识别性能瓶颈,然后根据识别的性能瓶颈进行修改。一般多线程系统,先按照线程的功能进行归类(组),把执行相同功能代码的线程作为一组进行分析。当使用堆栈进行分析的时候,以这一组线程进行统计学分析。如果一个线程池为不同的功能代码服务,那么将整个线程池的线程作为一组进行分析即可。
一般一个系统一旦出现性能瓶颈,从堆栈上分析,有如下三种最为典型的堆栈特征:
一个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
"Thread-243" prio=1 tid=0xa58f2048 nid=0x7ac2 runnable
[0xaeedb000..0xaeedc480]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)
... ...
at oracle.jdbc.driver.LongRawAccessor.getBytes()
at oracle.jdbc.driver.OracleResultSetImpl.getBytes()
- locked <0x9350b0d8> (a oracle.jdbc.driver.OracleResultSetImpl)
at oracle.jdbc.driver.OracleResultSet.getBytes(O)
... ...
at org.hibernate.loader.hql.QueryLoader.list()
at org.hibernate.hql.ast.QueryTranslatorImpl.list()
... ...
at com.wes.NodeTimerOut.execute(NodeTimerOut.java:175)
at com.wes.timer.TimerTaskImpl.executeAll(TimerTaskImpl.java:707)
at com.wes.timer.TimerTaskImpl.execute(TimerTaskImpl.java:627)
- locked <0x80df8ce8> (a com.wes.timer.TimerTaskImpl)
at com.wes.threadpool.RunnableWrapper.run(RunnableWrapper.java:209)
at com.wes.threadpool.PooledExecutorEx$Worker.run()
at java.lang.Thread.run(Thread.java:595)
"Thread-248" prio=1 tid=0xa58f2048 nid=0x7ac2 runnable
[0xaeedb000..0xaeedc480]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)
... ...
at oracle.jdbc.driver.LongRawAccessor.getBytes()
at oracle.jdbc.driver.OracleResultSetImpl.getBytes()
- locked <0x9350b0d8> (a oracle.jdbc.driver.OracleResultSetImpl)
at oracle.jdbc.driver.OracleResultSet.getBytes(O)
... ...
at org.hibernate.loader.hql.QueryLoader.list()
at org.hibernate.hql.ast.QueryTranslatorImpl.list()
... ...
at com.wes.NodeTimerOut.execute(NodeTimerOut.java:175)
at com.wes.timer.TimerTaskImpl.executeAll(TimerTaskImpl.java:707)
at com.wes.timer.TimerTaskImpl.execute(TimerTaskImpl.java:627)
- locked <0x80df8ce8> (a com.wes.timer.TimerTaskImpl)
at com.wes.threadpool.RunnableWrapper.run(RunnableWrapper.java:209)
at com.wes.threadpool.PooledExecutorEx$Worker.run()
at java.lang.Thread.run(Thread.java:595)
... ...
"Thread-238" prio=1 tid=0xa4a84a58 nid=0x7abd in Object.wait()
[0xaec56000..0xaec57700]
at java.lang.Object.wait(Native Method)
at com.wes.collection.SimpleLinkedList.poll(SimpleLinkedList.java:104)
- locked <0x6ae67be0> (a com.wes.collection.SimpleLinkedList)
at com.wes.XADataSourceImpl.getConnection_internal(XADataSourceImpl.java:1642)
... ...
at org.hibernate.impl.SessionImpl.list()
at org.hibernate.impl.SessionImpl.find()
at com.wes.DBSessionMediatorImpl.find()
at com.wes.ResourceDBInteractorImpl.getCallBackObj()
at com.wes.NodeTimerOut.execute(NodeTimerOut.java:152)
at com.wes.timer.TimerTaskImpl.executeAll()
at com.wes.timer.TimerTaskImpl.execute(TimerTaskImpl.java:627)
- locked <0x80e08c00> (a com.facilities.timer.TimerTaskImpl)
at com.wes.threadpool.RunnableWrapper.run(RunnableWrapper.java:209)
at com.wes.threadpool.PooledExecutorEx$Worker.run()
at java.lang.Thread.run(Thread.java:595)
"Thread-233" prio=1 tid=0xa4a84a58 nid=0x7abd in Object.wait()
[0xaec56000..0xaec57700]
at java.lang.Object.wait(Native Method)
at com.wes.collection.SimpleLinkedList.poll(SimpleLinkedList.java:104)
- locked <0x6ae67be0> (a com.wes.collection.SimpleLinkedList)
at com.wes.XADataSourceImpl.getConnection_internal(XADataSourceImpl.java:1642)
... ...
at org.hibernate.impl.SessionImpl.list()
at org.hibernate.impl.SessionImpl.find()
at com.wes.DBSessionMediatorImpl.find()
at com.wes.ResourceDBInteractorImpl.getCallBackObj()
at com.wes.NodeTimerOut.execute(NodeTimerOut.java:152)
at com.wes.timer.TimerTaskImpl.executeAll()
at com.wes.timer.TimerTaskImpl.execute(TimerTaskImpl.java:627)
- locked <0x80e08c00> (a com.facilities.timer.TimerTaskImpl)
at com.wes.threadpool.RunnableWrapper.run(RunnableWrapper.java:209)
at com.wes.threadpool.PooledExecutorEx$Worker.run()
at java.lang.Thread.run(Thread.java:595)
... ...
|
从堆栈看,有 51 个(socket)访问,其中有 50 个是 JDBC 数据库访问。其他方法被阻塞在 java.lang.Object.wait() 方法上。
减少锁的粒度,比如 ConcurrentHashMap 的实现默认使用 16 个锁的 Array(有一个副作用:锁整个容器会很费力,可以添加一个全局锁)
性能调优总有一个终止条件,如果系统满足如下两个条件,即可终止:
标签:soc aec hql sleep 共享资源 hashmap code nim 正在执行
原文地址:https://www.cnblogs.com/lfs2640666960/p/9302216.html