[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]使用JProfiler线上问题调查的小记录

上一篇:[GDS]NUC币种
下一篇:[GDS]GV2 fare就是最少两人的小团价

添加日期:2017/11/3 4:58:16 快速返回   返回列表 阅读1888次
(1)cpu占用过高,使用JProfiler分析,
某方法占用20%的cpu时间,一会功夫就达到了120秒,注意是秒。

方法很简单,将yyyyMMdd格式的字符串转换为yyyy-MM-dd格式
使用的DateFormat,先parse为Date,再format为带横杠的格式。

<1>先改为字符串拼接,cpu有所下降,但还是很高

<2>写了个main方法,调用该方法10万次,用时900毫秒的样子,
调用3000万次,用时竟然是6秒。
主要是substring内部的复制占时间,尝试用char等方式优化,效果不理想。

<3>
分析业务方法,发现外部单次查询,for循环套for循环,该方法可能会被调用上万次。
每秒300并发的话,就是300万次,累计起来占时就很高了。

然后发现,该方法的入口参数,是最外部传进来的一个参数,
也就是说,最外部转换一次就行了,不需要搞TM的3000万次。

最外层转换,加入参数map中,里层直接用转换结果进行比较。

搞定,收工。

(2)另一个方法占用40%的cpu,是线程池的submit方法


// 触发查询逻辑
ExecutorService exec = Executors.newFixedThreadPool(1);

TimeoutCallable withTimeoutCallable = new TimeoutCallable(queryList, this);

Future<List<QueryRespData>> future = null;
if (!exec.isShutdown()) {
    future = exec.submit(withTimeoutCallable);
}
exec.shutdown();



submit方法应该只是一个放队列的动作,占这么多cpu,不太可能。
所以觉得,可能是因为每次都做一个线程池的问题,
每秒300并发的话,做300个线程池,太浪费了

在方法顶部做了一个变量


    /**
     * 线程池(最大2000,队列满了重新执行).
     */
    private ExecutorService executor = new ThreadPoolExecutor(100, 2000,
            60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(),new ThreadPoolExecutor.CallerRunsPolicy());


然后下面直接submit一下就完事。

修改后,上线部署测试OK,问题解决。

程序员当初为什么这么写?因为都是抄来的,一知半解的。

(3)经过两步优化,服务器的cpu由长期90%降到了稳定的50%左右。
剩下一些是gzip,fastjson,网络io的时间,总cpu时间不多。

还有个业务方法占40%,不过看不出具体哪句耗时,
方法太复杂,以后有时间再慢慢分析。
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved