返回信息流不要轻信没有经过测试评估的性能优化
http://www.blogjava.net/yanhua365/archive/2006/07/18/58741.html
刚才看《代码大全》的样章,并于性能测试作者有这样一段话:
经验对性能优化也没有太大的帮助。一个人的经验或许来源于一台老掉牙的计算机,或许来自于过时的语言或编译器——在任何一种因素发生改变后,所有的经验之谈也会成为狗屁。除非对效果进行测量评估,否则你永远也无法确定某次优化所带来的影响。
接着作者举了一个例子来说明一次想当然的“性能优化”不但没有带来运行性能的改善,反而牺牲了代码的可读性。这一点我是深有体会的,下面说的也是我们发生在我们一个项目中的类似的案例。
我们最近的一个项目是用Hibernate来实现持久层的。有人提出利用Hibernate(循环)批量删除数据时有可能有性能瓶颈,因为大家都知道,Hibernate删除一条记录时会先把对应的实体类加载一次,这样才能维持缓存的完整性。于是有人提出利用Hibernate3的bulkUpdate来批量删除数据,这样就跳过了Hibernate的缓存,直接用一条SQL语句(类似于where id=1 or id=2...的形式)删除数据,性能就会大幅提高。
虽然我对这种做法能提高性能深信不疑(大家注意了,这种“深信不疑”后来被证明是一种想当然的或者经验主义错误),但我还是不赞成这种做法。首先,我觉得没有必要,因为我们分页显示数据时一页最多只显示8条,也就是说用户一次最多也只能删除8条,我认为这么少的数据即使用Hibernate循环8次来删除对性能的影响也不大。其次,用bulkUpdate会带来很多问题,比如可能会使缓存和数据库变的不一致了,尤其是在使用二级缓存的情况下,这会给程序埋下很大的隐患,另外一对多关系中的级联删除功能也失效了,在删除一个父对象时不得不手工删除子对象,这也为程序员忘记删除子对象而造成大量的垃圾数据带来了可能。最终,我的建议并没有被采取。我也默认了这样的结果,一是我做不了主,二呢我也相信bulkUpdate可以提高一些性能。
直到有一天很无聊,我想试一下倒底用bulkUpdate能快多少,于是写了两段程序来对比测试--测试的结果连我自己都有点不相信。在删除少量数据的时候,bulkUpdate不但不快,反而慢了两倍!只有一次要删除200条以上的数据时,bulkUpdate显示出优势来。要知道,我们一次最多只删除8条啊。我们想当然地进行了优化,到得了相反的效果,而且还牺牲了程序的简洁和优雅变得难以维护。是不是“陪了夫人又折兵”?
所以,最后《代码大全》中说:
我得到了一个教训,如果没有测量性能变化,那么你想当然的优化结果不过是代码变得更为晦涩难懂了。如果你认为没有必要通过测量来证实哪种方法更为有效,那么同样也没有必要牺牲代码可读性,而把赌注押在性能的提高上。
当然,我的测试结果也并不能说明全部问题,我的开发环境和服务器的环境还是有很大的差别的,但是可以肯定的是,我们想当然的优化往往并不可靠。
在这个项目中,类似的问题还很多。比如说两个关联对象只包括对方的ID属性(就是数据库的外键)而不是对方对象本身,这完全不符合面向对象的关联语义,而是数据库关系在对象领域生硬的映射。之所以这样做的理由是为了提高性能。真的能提高吗?能提高多少呢?比如说在HQL语句中不允许使用IN而只能拼一个长长的OR语句,据说这样可以提高数据库执行性能。真的能提高吗?后来听IBM的技术支持说DB2自己有SQL优化器的,如果IN真的比OR慢,我想优化器为什么不会优化一下呢?
我想,如果你认为需要对性能优化时,最好先做一下测试评估,看看这部分是不是真的是性能瓶颈;如果是的话,能不能尽量少地牺牲其它方面的利益来优化它。优化方案也要和以前的进行对比,真的优化了吗?
我们总以为自己很有经验,那么你猜一下,在一台普通的台式机上,循环10万次,每次New一个“Hello World”的字符串,需要多长时间呢?
这是一条镜像帖。来源:北邮人论坛 / soft-design / #9694同步于 2006/7/20
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖
不要轻信没有经过测试评估的性能优化 [ZZ FROM BLOGJAVA]
atian25
2006/7/20镜像同步0 回复
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。