对话马丁·福勒(Martin Fowler)——第六部分:性能与过程调优

第一部分:重构
第二部分:设计原则与代码所有权
第三部分:进化型设计
第四部分:灵活性与复杂性
第五部分:测试驱动开发
第六部分:性能与过程调优

  可维护性与效率

  比尔:我在丹佛机场的红地毯俱乐部(Red Carpet Club)[1]中常常碰到名人。今年夏天我碰到了 Calista Flockhart (卡莉斯塔·弗洛克哈特)[2], 而去年我碰到了你。我是个追星族,但是由于害怕哈里森·福特,没敢跟 Calista 搭讪。不过,你和我倒是坐下来喝了杯啤酒。记得当时你曾对我说过,应该以程序员能读懂的字符格式来序列化对象,而不是以二进制代码格式。当我提到字符格式 要比二进制码格式慢时,你说,从效率的角度来看,二进制代码格式使得软件更加难以维护。那么,能否请你谈谈关于序列化方式的具体案例?一般地说,你如何在 可维护性与效率之间寻找平衡点?

  马丁:效率永远是第一位的,前提是你能正确理解它。很多时候问题在于,人们以为做某些事情是为了效率着想,但他们却从不使用性能分析器(profiler)。如果你出于效率的考虑而做某件事,但却不使用性能分析器,那么你所宣称的根本就不着调。

  序列化所牵扯的问题要多一些。使用二进制代码做序列化的问题之一就是你无法去查看结果。当你需要存储序列化的对象时,这个问题就更加突 出。Java 的一个典型问题就是如果你改变了一个类,那么就无法读取以前所序列化的对象。类似的,如果一个客户端和一台服务器正通过序列化的对象进行通讯,假如一端的 数据结构进行了更新而另一端没有,那么整个通讯就彻底失效了。

  有一个小窍门可以让你绕开这个问题。不要序列化对象本身,而是把数据从对象中提取出来,放到一个字典里,然后再序列化那个字典。这么做会使你能够应对一些变化。

  比尔:但是,字典是“不明确的”。我们之前刚刚说起过这点。

  马丁:的确,字典不是“明确的”。不过,如果你往类里添加一个字段,并把这个多出来的值放到字典里 的话,不会有什么问题。因此,这是一个比较强壮的机制。XML 一般也比较强壮,因为你可以对你所不了解的数据视而不见。二进制序列化的主要问题就是它的脆弱性。在我的书《企业应用架构模式》中,更多地提到了序列化的 方式。例如,在数据库中传输和存储数据时,就需要考虑介于字符和二进制之间的序列化格式。

  编写可性能调优的软件

  比尔:你在《重构》一书中写道:“编写能快速运行的软件的秘诀就在于先编写可性能调优的软件,然后对执行速度进行调优。” 我该怎样编写可性能调优的软件呢?

  马丁:只要做到软件结构合理就可以。

  比尔:怎么讲?

  马丁:因为结构合理的软件可以更容易地进行改动。

  比尔:也就是说,这时候软件要更容易地进行改动,不是为了添加新功能,而是为了提升已有功能的性能。

  马丁:结构合理的软件能够更容易地进行调优。你应该首先专心于让软件结构合理、设计清晰,然后,在性能调优器的引导下,完成性能优化过程。

  优化

  马丁:还有一件事需要牢记:性能优化与版本和具体的实现是密切相关的。当你拿到 Java 的一个新版本时,一定要把以前所做的优化都撤消,然后重走一遍优化过程,以确保那些优化手段仍然奏效。通常你会发现,你为上一个版本的虚拟机 (virtual machine)或优化型编译器(optimizing compiler)所做的性能优化往往使当前的版本变慢,也即,之前的优化手段如今往往起到适得其反的作用。

  比尔:要记住以前为了提升性能都做了哪些改动可不是件容易的事情。

  马丁:你必须这么做——先撤销,再重新应用。我知道这不容易。这就要求你对优化过程中所做的每个改动都要有详细的记录。要知道,旧的优化所造成的一些微不足道的性能损失,在新的版本下有时候可能会变得非常显著。

  Craig Larman (拉曼 C [3]) 曾经讲过一个故事,我到现在都还很喜欢这个故事。Craig 有一次在 JavaOne 的大会上做性能优化的讲座。他提到了两个广为人知的技术:对象池(object pooling)和线程池(thread pooling)。对象池就是重用已有的对象,而不是每次都创建新的对象。线程池的原理基本类似。讲座结束后,有两个人来到 Craig 跟前。这两个人都是设计高性能虚拟机的。其中一个虚拟机是 Hotspot,另一个好像是 JRocket。一个人告诉 Craig,线程池的效果不错,但对象池则使得虚拟机的运行变慢;而另一个人告诉 Craig 的恰恰相反。

 所以,你有可能在一种虚拟机上优化了性能,但拿到另一种虚拟机上,却减慢了其运行速度。对此,你要特别小心。对象池就是一个很好的例子。 很多人热衷于对象池,但起码有一半的情况下,人们并不去测量对象池的效果到底是好是坏。在 Java 的早期日子里,对象池非常重要,因为垃圾回收(garbage collection)功能还不是很完善。但在垃圾回收技术更新换代之后,对象池的效果就大大降低了,因为那些生存周期很短的对象可以被低成本地回收。只 有那些生存周期很长的对象,才适合使用对象池技术,因为对它们进行垃圾回收的成本很高。

  从这里可以看出,规则也是在不断变化的。这就是为什么要对性能调优很仔细的原因所在。不要妄想根据源代码就能预测机器会做什么。当你与虚拟机或优化型编译器打交道时,性能调优是唯一的手段,因为编译器和虚拟机所做的事情,远远超出你的想象。记住,不要预测,要实测。

  模式的意义

  比尔:你在《设计是否已死》这篇文章中表示:“对我来说,模式仍然是至关重要的,”尤其是考虑到极限编程的话。那么今天,模式处于一个什么样的地位呢?

  马丁:模式给了我们瞄准的目标。我还会做一些预先设计。模式就是用来干这个的。模式还给了我们以重 构的目标。我们得以知道我们改进的方向。了解模式还有助于我们找到设计美感,因为模式至少都是一些好的设计。你可以从它们身上学到很多。因此,我仍然认为 模式起着重要的作用。其实,很多积极推动极限编程运动的人,本身就活跃在模式社区里。这两个社区在很大程度上是重叠的。

  敏捷宣言

  比尔:最后一个问题,敏捷宣言到底是怎么一回事?

  马丁:哦,那是一群投入到敏捷软件方法领域的人,聚在一起,彼此印证心得。这个领域包括极限编 程,scrum,crystal,修错驱动开发(fix-driven development),和动态系统开发方法(DSDM)。我们意识到我们之间有很多共同之处,因此决定把我们所认同的写下来。我们把这份宣言看作是一 种象征——在这面大旗下汇聚了支持此类方法的人们。在那次聚会中,我们决定使用“敏捷方法”这个词。这份宣言可以作为敏捷软件开发的一个定义。借助这份宣 言,我们共同呼吁,软件业的主流应该朝着这个方向前进。

  比尔:让我们来看看四条原则中的一条:“个人与交互重于过程和工具”。这是什么意思?

  马丁:这条原则大意是说,与其借重过程和工具来加强对软件开发的管理,不如更多地关注于团队及其成员,关注于每个个体以及他们之间在个人层面上的交互。

  比尔:你是说提升他们的技能么?

  马丁:要远比这个丰富得多。它包括了提升技能;它还包括要竭尽全力使程序员们身心愉悦,从而得以留 住人才;它还意味着更认真地对待个性冲突,注重人与人的相处,而不是试图找出某个完美的软件开发过程,然后要求大家都来遵守这个过程。我对这条原则的理解 是,应该是团队选择适合其的软件开发过程,而不是让团队来适应指定的开发过程。

  尽管在那次聚会上,我们中的许多人都津津乐道于自己所采用的开发过程,并且我们当中的几个人还是软件工具销售商,但我们一致同意,对于一个项目的成功来说,软件开发过程和工具只是次要的因素,最主要的因素还是团队,是团队中的成员,是他们人性化的合作与努力。

====================================分割线================================

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-05 14:59:37

对话马丁·福勒(Martin Fowler)——第六部分:性能与过程调优的相关文章

jvm系列(六):Java服务GC参数调优案例

本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题.我个人特别喜欢这种实战类的内容,经原作者的授权同意,将文章分享于此.备注部分为本人添加,主要起到说明的作用. 原文出处:https://segmentfault.com/a/1190000005174819 背景以及遇到的问题 我们的Java HTTP服务属于OLTP类型,对成功率和响应时间的要求比

BaaS云架构核心模式之Serverless架构 - 用服务代替服务器(Martin Fowler)

Martin Fowler最近非常推崇的serverless架构模式,是BaaS云架构实现的核心架构模式. Martin Fowler在2016.6.17号发表了一篇博客: <Serverless Architectures>,引起业界广泛关注: 在这篇博客里,他介绍了serverless架构,以及FaaS,Microservice,Docker等流行的架构和概念,描述了Amazon AWS lambda的价值, 进一步将这种云时代的架构清晰的展现在大家的视野里. 本文很多内容来自这篇博客,让

Martin Fowler对将page对象用于Web测试的基本经验法则

本文源自Martin Fowler,文章最初由ThoughtWorks工程师黄博文翻译在自己的博客上,并由译者本人推荐至InfoQ中文站博文共赏专栏.本译文在Martin Fowler本人的许可下,由InfoQ中文站进行修订后,在这里给大家分享. 当你在为Web页面编写测试时,你需要操作该Web页面上的元素来点击链接或验证显示的内容.然而,如果你在测试代码中直接操作HTML元素,那么你的代码是及其脆弱的,因为UI会经常变动.一个page对象可以封装一个HTML页面或部分页面,你可以通过提供的应用

Martin Fowler竟然不是第一个提出微服务架构概念的?

王磊:前ThoughtWorks首席咨询师,<微服务架构与实践>作者,翻译有<DevOps Handbook>,国内较早倡导和实践微服务的先行者,有丰富的微服务/DevOps/持续交付实战经验 微服务架构那点事 相信很多朋友了解微服务架构都是从Martin Fowler的那篇文章开始.而实际上,Martin却并不是最早谈及微服务架构的,本篇文章就和你聊聊微服务架构定义的那点事. 最易懂的版本 Martin Fowler的这篇文章<Microservices>通俗易懂的讲

Martin Fowler谈如何理解事件驱动

去年年底,ThoughtWorks内部开展了一个研讨会,讨论"事件驱动"应用程序的性质.在过去的几年里,他们建立了许多基于事件的系统,有被称赞,也有被吐槽.ThoughtWorks的北美办公室组织了一次峰会,来自世界各地的ThoughtWorks高级开发人员在会上分享了他们的想法. 峰会的最大结果是得出这样的一个结论:当人们谈论"事件"时,他们实际上意味着一些完全不同的事情. 所以Martin Fowler花了很多时间试图从中挑出一些有用的模式, 本文就是对这些内容

读Martin Fowler&amp;#39;s 《Patterns of Enterprise Application Architecture》有感

作为一本技术指导书,显然这本书有些outdated了,但想想现在的一些框架,架构正是基于这本书的思想构建的,还是不免对作者当时的Vision感到钦佩.出于对这些思想本源的追索,以及对历史的追溯.还是很有必要浏览这本经典著作的,对于这个500页的书,我看的比较快,只是跳一些感兴趣的点着重看下,事实证明还是很有收获的. POJO 起源:J2EE才出现时,尽管EJB2.0 特别是它的Entity Bean 给开发和调试带来了很多不便,但是在vendor的怂恿和对新技术的盲从下,很多公司还是采用了这个后

企业应用架构模式阅读笔记 - Martin Fowler

1. 数据读取

memcached(六)调优经验

一 监控 查看memcahe服务器的状态,通常我们使用2个命令 1)telnet 127.0.0.1 11211 查看全局 stats 查看slab stats slabs 查看item stats items 2)vmstat 1 -S M 二 调优 根据笔者个人经验,memcached调优需要注意一下几点. 1)节点过热 如果memcached有个别节点容量耗光,同时并发很大.那么需要重新分配一致性hash的服务器分布.或者增加虚拟节点 2)节点预热 如果线上压力非常大,memcache集群

JVM调优总结(六)-分代垃圾回收详述2

分代垃圾回收流程示意