Effective Java(3rd)-Item67 谨慎优化

  有三条关于优化的格言是每个人都应该知道的:
比起其他任何单一的原因(包括盲目的愚蠢),更多的计算罪恶是在效率的名义下犯下的(不一定能实现)。
——William A. Wulf [Wulf72]
我们应该忘记小的效率,比如97%的时间:过早的优化是万恶之源。
——Donald E. Knuth [Knuth74]
在优化问题上,我们遵循两条规则:
规则1。不要这样做。
规则2(只适用于专家)。先不要这样做——也就是说,直到你有了一个完全清晰的、未优化的解决方案。
——M. A. Jackson [Jackson75]

  所有这些格言都比Java编程语言早了20年。它们告诉我们一个关于优化的深刻事实:这很容易弊大于利,尤其是如果您过早地进行优化。此过程中,您可能会生成既不快速也不正确且无法轻松修复的软件。
  不要为了性能而牺牲合理的架构原则。努力编写好的程序,而不是快速的程序。如果一个好的程序不够快,它的架构将允许对其进行优化。好的程序体现了信息隐藏的原则:在可能的情况下,它们在单个组件中本地化设计决策,因此可以在不影响系统其余部分的情况下更改单个决策(item15)。

  这并不意味着在程序完成之前可以忽略性能问题。实现问题可以通过以后的优化来解决,但是如果不重写系统,就不可能解决限制性能的普遍架构缺陷。事后更改设计的基本方面可能导致结构不良的系统难以维护和进化。因此,您必须在设计过程中考虑性能。
  尽量避免限制性能的设计决策。设计中最难以更改的组件是那些指定组件之间以及与外部世界的交互的组件。这些设计组件中最主要的是api、线级协议和持久数据格式。这些设计组件不仅难以或不可能在事后更改,而且所有这些组件都可能对系统能够达到的性能造成重大限制。
  考虑API设计决策的性能结果。使公共类型可变可能需要大量不必要的防御性复制(item50 )。类似地,在一个公共类中使用继承(在这个类中组合将是合适的)将该类永远绑定到它的超类,这会人为地限制子类的性能( item18)。最后一个例子,在API中使用实现类型而不是接口将您绑定到特定的实现,即使将来可以编写更快的实现(item64)。

  API设计对性能的影响是非常真实的。考虑java.awt.Component类中的getSize方法。这个性能关键的方法返回一个维度实例的决定,加上维度实例是可变的决定,强制该方法的任何实现在每次调用时分配一个新的维度实例。尽管在现代VM上分配小对象并不昂贵,但不必要地分配数百万个对象会对性能造成实际损害。
  存在几种API设计替代方案。理想地,Dimension 应该是不可变的( item17)。或者,getSize可以被返回Dimension对象的各个原始组件的两个方法所替代。事实上,出于性能原因,在Java 2的组件中添加了两个这样的方法。然而,现有的客户端代码仍然使用getSize方法,并且仍然受到原始API设计决策的性能影响。

  幸运的是,通常情况下,好的API设计与好的性能是一致的。为了获得良好的性能而扭曲API是一个非常糟糕的想法。导致您扭曲API的性能问题可能在平台或其他底层软件的未来版本中消失,但是扭曲的API和随之而来的支持难题将永远伴随着您。
  一旦您仔细地设计了您的程序并生成了一个清晰、简洁、结构良好的实现,那么可能是时候考虑优化了,假设您还不满意程序的性能。
  记得Jackson的两条优化规则是“不要做”和“(只针对专家)”。先别这么做。”他本可以再加一个:在每次尝试优化之前和之后测量性能。你可能会对你的发现感到惊讶。通常,尝试的优化对性能没有可测量的影响;有时候,他们让事情变得更糟。主要原因是很难猜测程序将时间花在哪里。程序中您认为很慢的部分可能并没有错,在这种情况下,您将浪费时间来优化它。一般认为,程序将90%的时间花在10%的代码上。
  分析工具可以帮助您决定将优化工作的重点放在哪里。分析工具可以帮助您决定将优化工作的重点放在哪里。除了关注您的调优工作之外,这还可以提醒您需要进行算法更改。如果程序中潜伏着二次(或更糟)算法,那么再多的调优也无法解决这个问题。你必须用一个更有效的算法来代替这个算法。系统中的代码越多,使用分析器就越重要:这就像大海捞针:草堆越大,金属探测器就越有用。另一个值得特别提及的工具是jmh,它不是一个分析器,而是一个微基准测试框架,提供了对Java代码的详细性能无与伦比的可见性。
  与C和c++等更传统的语言相比,Java更需要度量尝试优化的效果,因为Java的性能模型更弱:各种基本操作的相对成本定义得不是很好。程序员编写的内容和CPU执行的内容之间的“抽象鸿沟”更大,这使得可靠地预测优化的性能结果变得更加困难。有很多关于绩效的神话流传开来,但最终被证明是半真半假或彻头彻尾的谎言。
  Java的性能模型不仅定义不清,而且在不同的实现之间、不同的发布之间、不同的处理器之间都有所不同。如果您要在多个实现或多个硬件平台上运行程序,那么度量优化对每个平台的效果是很重要的。有时候,您可能会被迫在不同实现或硬件平台上的性能之间进行权衡。
  自本项目首次编写以来的近20年里,Java软件栈的每个组件都变得越来越复杂,从处理器到vm再到库,Java运行的各种硬件都有了极大的增长。所有这些加在一起,使得Java程序的性能比2001年更难以预测,而对它进行度量的需求也相应增加。
  总而言之,不要努力写快程序——要努力写好程序;速度会跟上来的。但是在设计系统时一定要考虑性能,特别是在设计api、线级协议和持久数据格式时。当您完成了系统的构建之后,请度量它的性能。果足够快,就完成了。如果没有,利用分析器找到问题的根源,并对系统的相关部分进行优化。第一步是检查算法的选择:再多的底层优化也不能弥补算法选择的不足。根据需要重复这个过程,在每次更改之后测量性能,直到您满意为止。

本文写于2019.7.19,历时1天

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容

  • [{"reportDate": "2018-01-23 23:28:49","fluctuateCause": n...
    加勒比海带_4bbc阅读 766评论 1 2
  • 目录: Android:Android 0.*Android 1.*Android 2.*Android 3.*A...
    敲代码的令狐葱阅读 3,816评论 0 2
  • 关于小时候的记忆,印象最深的早餐,除了牛肉粿条就是粿汁。巷口是早市,算是小规模的蔬菜批发市场。早上四五点钟就陆陆续...
    瑰琦2020阅读 515评论 3 1
  • 21天减脂第一天,目标:100引体,500个30公斤划船。10公里跑步。 说实话,对于这几个目标,单独做的话我应该...
    嘟嘟白白爸爸阅读 127评论 0 0
  • 生活中只有一种英雄主义,那就是认清生活的真相之后依然热爱生活。----《米开朗琪罗》罗曼·罗兰 7月24日,中二少...
    中二少女裸辞纪实阅读 198评论 0 0