1700452178
编写高质量代码:改善Java程序的151个建议 建议135:必须定义性能衡量标准
1700452179
1700452180
出现性能问题不可怕,可怕的是没有目标,用户只是说“我希望它非常快”,或者说“和以前一样快”,在这种情况下,我们就需要把制定性能衡量标准放在首位了,原因有两个:
1700452181
1700452182
(1)性能衡量标准是技术与业务之间的契约
1700452183
1700452184
“非常快”是一个直观性的描述,它不具有衡量的可能性,对技术人员来说,一个请求在2秒钟之内响应就可以认为是“非常快”了,但对业务人员来说,“非常快”指的是在0.5秒内看到结果—看,出现偏差了。如果我们不解决这种偏差,就有可能出现当技术人员认为优化结束的时候,而业务人员还认为系统很慢,仍然需要提高继续性能,于是拒不签收验收文档,这就产生商务麻烦了。
1700452185
1700452186
(2)性能衡量标志是技术优化的目标
1700452187
1700452188
性能优化是无底线的,性能优化得越厉害带来的副作用也就明显,例如代码的可读性差,可扩展性降低等,比如一个乘法计算,我们一般是这样写代码的:
1700452189
1700452190
int i=100*16;
1700452191
1700452192
如果我们为了提升系统性能,使用左移的方式来计算,代码如下:
1700452193
1700452194
int i=100<<4;
1700452195
1700452196
性能确实提高了,但是也带来了副作用,比如代码的可读性降低了很多,要想让其他人员看明白这个左移是何意,就需要加上注释说“把100扩大16倍”,这在项目开发中是非常不合适的。因此为了让我们的代码保持优雅,减少“坏味道”的产生,就需要定义一个优化目标:优化到什么地步才算结束。
1700452197
1700452198
明白了性能标准的重要性,就需要在优化前就制定好它,一个好的性能衡量标准应该包括以下KPI(Key Performance Indicators):
1700452199
1700452200
核心业务的响应时间。一个新闻网站的核心业务就是新闻浏览,它的衡量标准就是打开一个新闻的时间;一个邮件系统的核心业务就是邮件发送和接收速度;一个管理型系统的核心就是流程提交,这也就是它的衡量标准。
1700452201
1700452202
重要业务的响应时间。重要业务是指在系统中占据前沿地位的业务,但是不会涉及业务数据的功能,例如一个业务系统需要登录后才能操作核心业务,这个登录交易就是它的重要交易,比如邮件系统的登录。
1700452203
1700452204
当然,性能衡量标准必须在一定的环境下,比如网络、操作系统、硬件设备等确定的情况下才会有意义,并且还需要限定并发数、资源数(如10万数据和1000万的数据响应时间肯定不同)等,当然很多时候我们并没有必要白纸黑字地签署一份协约,我们编写性能衡量标准更多地是为了确定一个目标,并尽快达到业务要求而已。
1700452205
1700452206
1700452207
1700452208
1700452210
编写高质量代码:改善Java程序的151个建议 建议136:枪打出头鸟—解决首要系统性能问题
1700452211
1700452212
在一个系统出现性能问题的时候,很少会出现只有一个功能有性能问题(一个功能出现性能问题的情况非常容易解决,基本上不会花费什么时间),系统一旦出现性能问题,也就意味着一批的功能都出现了问题,在这种情况下,我们要做的就是统计出业务人员认为重要而且缓慢的所有功能,然后按照重要优先级和响应时间进行排序,并找出前三名,而这就是我们要找的“准出头鸟”。
1700452213
1700452214
“准出头鸟”找到了,然后再对这三个功能进行综合分析,运行“望闻问切”策略,找到问题的可能根源,然后只修正第一个功能的性能缺陷,再来测试检查是否解决了这个问题,紧接着是第二个、第三个,循环之。可能读者会产生疑问:为什么这里只修正第一个缺陷,而不是三个一起全部修正?这是因为第一个性能缺陷才是我们真正的出头鸟,在我做过的性能优化项目中超过80%的只要修正了第一个缺陷,其他的性能问题就会自行解决或非常容易解决,已经不成为问题了。
1700452215
1700452216
比如BBS系统,从用户登录到用户浏览、发帖都非常缓慢,经过逐步筛选,确定登录就是“出头鸟”,需要着重解决,代码如下:
1700452217
1700452218
class Login extends HttpServlet{
1700452219
1700452220
public void doGet(HttpServletRequest req, HttpServletResponse resp){
1700452221
1700452222
//从req中获得用户名和密码
1700452223
1700452224
String userName=……;
1700452225
1700452226
String passwd=……;
[
上一页 ]
[ :1.700452177e+09 ]
[
下一页 ]