JAVA优化篇 如何找到运行缓慢的线程

引入

  JAVA提供了一些分析DUMP的工具,比如jmap,visualvm 等

  JAVA还有寻找线程状态的工具,jstack等

  数据库也有检查连接数,连接状态的命令,status,processlist等

  代码中也可以添加一些时间的信息,对比信息发现可优化的地方

  但这些都不是今天要记录的内容,今天要做的是使用一个比较暴力的方式查找出高并发模式下运行缓慢的线程

正文

  写高并发的时候经常会遇到的问题:

    单独观察每个分支线程或者主线程时,都执行地非常快,但是总体上运行的TPS却并不高,没有达到期望的值

    更换环境,或者调大运行内存和CPU后,情况仍然不见好转

  这时候有个办法是,找出每个线程的运行过程,寻找出耗时较大的代码段,再对代码进行分析

  脚本我已经写好了:

#!/bin/bash
parseLog(){
##初始值
upLine="blank"
last_time_pre="blank"
last_time_post="blank"
cat "$1" | while read line
do
time_pre=`echo "$line" | awk '{print$1}'`
time_post=`echo "$line" | awk '{print$2}'`
if [[ `echo "$time_post" | grep ":"` != "" ]]
then
if [[ "$upLine" == "blank" ]]
then
upLine=${line}
last_time_pre=`echo "$line" | awk '{print$1}'`
last_time_post=`echo "$line" | awk '{print$2}'`
total2="$last_time_pre"" $last_time_post"
last_time_pre=`date +%s -d "$total2"`
last_time_pre=`expr "$last_time_pre" \* `
last_time_post=`echo ${last_time_post::}`
else
total="$time_pre"" $time_post"
time_pre=`date +%s -d "$total"`
time_pre=`expr "$time_pre" \* `
time_post=`echo ${time_post::}`
time_end=`expr "$time_pre" + "$time_post"`
time_begin=`expr "$last_time_pre" + "$last_time_post" + "$2"`
last_time_pre=${time_pre}
last_time_post=${time_post}
if [[ "$time_end" -gt "$time_begin" ]]
then
echo ${upLine} >> result.log
echo ${line} >> result.log
fi
upLine=${line}
fi
fi
done
} if [[ ! -n "$1" ]] || [[ ! -n "$2" ]] || [[ ! -n "$3" ]]
then
echo [log file] [interval millis] [key words]
exit
fi awk '{num[$4]++}
END{for(k in num)print k,"----",num[k]|"sort -k 3 -rn"}' "$1" |
head -n | awk '{str[$1]++} END{for (s in str)print s}'| grep "$3" > thread.log ##对上述输出的每一个线程做分析处理,调用parseLog
cat thread.log | while read line
do
grep "\""${line}"\"" "$1" > temp.log
parseLog temp.log $
done
exit

  这个脚本有个基础条件是,分析的日志必须得是按照一定规范输出的日志,输出字段中带有时间和线程名

  脚本传参:

JAVA优化篇 如何找到运行缓慢的线程

  获得可以分析的所有线程,按照数量排序,并只获得前15个

JAVA优化篇 如何找到运行缓慢的线程

  接下来对每一个过滤出来的线程做分析处理

JAVA优化篇 如何找到运行缓慢的线程

  最后就是分析日志的方法了

  主要思路是,用下一行的时间减去上一行的时间,如果超过给定的值,就将两行都输出到指定文件。

JAVA优化篇 如何找到运行缓慢的线程

  执行效果:

[utap@host145 logs]$ sh pick_thread.sh bb.log  timer
timerQ_3-service-#]
[utap@host145 logs]$ cat result.log
-- ::00.371 [DEBUG] [TaskRule:][printExpr] [timerQ_3-service-#] [] - TaskRule printExpr i-j=-, expr[i].elementAt(j).m_min=, m_max=
-- ::00.373 [DEBUG] [TaskRule:][printExpr] [timerQ_3-service-#] [] - TaskRule printExpr i-j=-, expr[i].elementAt(j).m_min=, m_max=^C

  方便再次使用到吧,地址在 https://github.com/garfieldcgf/notes/tree/master/operations/bin

上一篇:如何诊断oracle数据库运行缓慢或hang住的问题


下一篇:css3 的 calc()函数在布局中的使用----头部高度固定,页面正好占满一屏