首页 » 编写高质量代码:改善Java程序的151个建议 » 编写高质量代码:改善Java程序的151个建议全文在线阅读

《编写高质量代码:改善Java程序的151个建议》建议136:枪打出头鸟解决首要系统性能问题

关灯直达底部

在一个系统出现性能问题的时候,很少会出现只有一个功能有性能问题(一个功能出现性能问题的情况非常容易解决,基本上不会花费什么时间),系统一旦出现性能问题,也就意味着一批的功能都出现了问题,在这种情况下,我们要做的就是统计出业务人员认为重要而且缓慢的所有功能,然后按照重要优先级和响应时间进行排序,并找出前三名,而这就是我们要找的“准出头鸟”。

“准出头鸟”找到了,然后再对这三个功能进行综合分析,运行“望闻问切”策略,找到问题的可能根源,然后只修正第一个功能的性能缺陷,再来测试检查是否解决了这个问题,紧接着是第二个、第三个,循环之。可能读者会产生疑问:为什么这里只修正第一个缺陷,而不是三个一起全部修正?这是因为第一个性能缺陷才是我们真正的出头鸟,在我做过的性能优化项目中超过80%的只要修正了第一个缺陷,其他的性能问题就会自行解决或非常容易解决,已经不成为问题了。

比如BBS系统,从用户登录到用户浏览、发帖都非常缓慢,经过逐步筛选,确定登录就是“出头鸟”,需要着重解决,代码如下:


class Login extends HttpServlet{

public void doGet(HttpServletRequest req, HttpServletResponse resp){

//从req中获得用户名和密码

String userName=……;

String passwd=……;

//由登录逻辑处理登录

boolean loginSuccess=loginBiz.login(user, passwd);

if(loginSuccess){

//登录成功,签到

Checker.sign(userName);

}else{

//登录不成功,记录日志

log.warn(userName+",登录失败!")

}

}

}


这是一个早期Web应用的典型验证代码,先验证用户是否登录成功,然后决定是否向Session中写入信息。在该BBS系统中,分析发现login和sign操作都非常耗时,那就首先跟踪login,代码如下:


class LoginBiz{

public void login(String_user, String_password){

//根据用户名获得用户对象

User u=userDao.getUserByUser(_user);

return u!=null&&u.getPasswd().equals(_password);

}

}


追踪到这里,发现从数据中取出用户对象的效率很低,但是数据库的CPU、内存、I/O都没有问题,而且没有到达最大连接数。继续追踪下去,终于发现问题了:数据库的版本和JDBC的版本不一致,虽然在进行所有的连接、执行SQL、断开等操作时都没有出现任何问题,但在多表的联合查询中速度非常慢。问题定位了,将其替换成数据库匹配的驱动程序,登录问题马上得到解决,并且其他所有性能慢的问题都解决了,归根结底其实都是数据库驱动问题引起的。

解决性能问题时,不要把所有的问题都摆在眼前,这只会“扰乱”你的思维,集中精力,找到那个“出头鸟”,解决它,在大部分情况下,一批性能问题都会迎刃而解,而且我们的用户关注最多的可能就是系统20%的功能,可能我们解决了这一部分,已经达到了用户的预期目标,也就标志着我们的优化工作可以结束了。

注意 解决性能优化要“单线程”小步前进,避免关注点过多而导致精力分散。