作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
凯文·布洛赫
验证专家 在工程
8 的经验

Kevin拥有超过20年的全栈、桌面和独立游戏开发经验. 他最近专门研究PostgreSQL、JavaScript、Perl和Haxe.

专业知识

分享

这几乎是值得保证的,真的. 从新手到 专家, 从架构到ASM, 并优化从机器性能到开发人员性能的任何东西, 你和你的团队很有可能无法实现自己的目标.

什么? Me? My 团队?

这是一个相当严重的指控. 让我解释一下.

优化并不是终极目标,但它同样难以实现. 我想与你分享一些简单的技巧(以及成堆的陷阱),以帮助你的团队从一个自我破坏的经历转变为一个和谐的经历, 实现, 平衡, 和, 最终, 优化.

什么是过早优化?

过早优化是试图优化性能:

  1. 第一次编写算法时
  2. 在基准测试确认之前,您需要
  3. 在分析确定哪些地方值得优化之前
  4. 在比您的项目当前要求的更低的级别

我是个乐观主义者,擎天柱.

至少,在我写这篇文章的时候,我会假装是个乐观主义者. 至于你,你可以假装你的名字是擎天柱,这样你会更直接.

作为科技行业的人,你可能有时会想,这是怎么可能的 美元一年 然而,尽管我们进步了这么多,这在某种程度上还是可以接受的标准 美元的任务 如此烦人的耗时. 你想变瘦. 非常高效。. 太棒了. 就像那些招聘启事所要求的Rockstar程序员, 但是有了领导才能. 所以当你的团队写代码时, 你鼓励他们第一次就把事情做对(即使“对”是一个高度相对的术语), 这里). 他们知道这是聪明的程序员的方式, 也是那些不需要浪费时间进行重构的人的方法.

我觉得. 有时候,完美主义的力量在我内心也很强烈. 你想让你的团队花 现在是时候拯救了 很多 时间的流逝,因为每个人都艰难地度过了他们的那份 “别人写的烂代码(他们到底在想什么?).” 这是SCOPWWHWTT的缩写,因为我知道你喜欢难以发音的缩写.

我也知道你不希望你的团队的代码成为他们自己或其他人的代码.

所以,让我们来看看可以做些什么来引导你的团队朝着正确的方向前进.

什么 优化:欢迎来到这是一门艺术

首先,当我们想到程序优化时,我们通常会立即假设我们在谈论 表演. 甚至 已经比看起来更模糊了(速度?? 内存使用情况? 等.我们就讲到这里吧.

我们扯平吧 更多的 模棱两可的! 刚开始的时候.

我网状的大脑喜欢尽可能地创造秩序, 所以我需要非常乐观的心态来考虑我要说的是什么 好事.

有一个简单的(性能)优化规则 不要这样做. 这听起来很容易严格遵守,但并不是每个人都同意. 我也不完全同意. 有些人一开始就会写出比别人更好的代码. 希望, 对于任何一个人, 他们在一个全新项目中编写的代码质量通常会随着时间的推移而提高. 但我知道, 对于许多程序员来说, 但事实并非如此, 因为他们知道的越多, 就会有更多的方式诱使他们过早地进行优化.

对于许多程序员来说,他们知道的越多,就越容易过早地进行优化.

所以这 不要这样做 这并不是一门精确的科学,只是为了对抗典型的技术人员解决谜题的内在冲动. 毕竟,这是吸引许多程序员进入这门手艺的首要原因. 我明白了. 但是请他们 保存它要抵制诱惑. 如果你需要一个解谜的出口 现在在美国,人们可以玩周日报纸上的数独游戏,或者拿起一本门萨书,或者去玩 代码打高尔夫球 有一些人为的问题. 但在适当的时候再把它取出来. 几乎总是 这是比预先优化更明智的方法.

记住,这种做法是臭名昭著的,人们问是否 过早的优化是万恶之源. (我不会走那么远,但我同意这种观点.)

我并不是说我们应该在设计的每一个层面上都选择我们所能想到的最愚蠢的方式. 当然不是. 但我们可以选择最聪明的,而不是选择最聪明的 考虑其他价值:

  1. 最容易向你的新员工解释的
  2. 最有可能通过经验最丰富的开发人员的代码审查
  3. 最可维护的
  4. 写得最快
  5. 最容易测试
  6. 最便携
  7. 等.

但问题的难点就在这里. 这不仅仅是关于 避免优化速度、代码大小、内存占用、灵活性或面向未来的能力. 这关乎平衡,关乎你所做的是否真的符合你的价值观和目标. 这完全取决于情境,有时甚至无法客观衡量.

这是一门艺术. (C.f. 计算机程序设计艺术.)

为什么这是一件好事? 因为生活就是这样. 它是混乱的. 我们以编程为导向的大脑有时非常想在混乱中创造秩序,结果却适得其反地加剧了混乱. 这就像试图强迫别人爱你的矛盾. 如果你认为你已经成功了, it’s no longer love; meanwhile, 你被控劫持人质, 你可能需要比以往更多的爱, 这个比喻是我能想到的最尴尬的比喻之一.

无论如何, 如果你认为你找到了一个完美的系统, 好吧,趁它还在的时候好好享受吧, 我猜. 没关系,失败是学习的好机会.

过早的优化通常会使你的产品复杂化.

牢记用户体验

让我们来探讨一下用户体验如何适应这些潜在的优先级. 毕竟,在某种程度上,即使想要某些东西表现良好,也是关于UX的.

如果你在做UI, 无论代码使用什么框架或语言, 会有一定数量的样板和重复. 就程序员的时间和代码清晰度而言,尽量减少这种情况肯定是有价值的. 为了帮助你平衡轻重缓急,我想分享几个故事.

在一份工作中, 我工作的公司使用的是一个基于固执己见的技术栈的闭源企业系统. 事实上, 它是如此固执己见,以至于把它卖给我们的供应商拒绝做不符合堆栈观点的UI定制, 因为这对他们的开发者来说太痛苦了. 我从来没用过他们的堆栈, 所以我不会因此谴责他们, 但事实是,这“对程序员有好处”, 这对用户来说是件坏事 so 在某些情况下对我的同事来说很麻烦,所以我最终编写了一个第三方附加组件来重新实现系统UI的这一部分. (这是一个巨大的生产力助推器. 我的同事们都很喜欢! 十多年后,它是 仍然 节省了每个人的时间和挫败感.)

I’m not saying 那 opinionation is a problem in itself; just 那 too much of it became a problem in our case. 作为一个反例,Ruby on Rails最大的吸引力之一就是它 is 固执己见,在前端生态系统中,人们很容易因为太多的选择而感到眩晕. 给我一些有观点的东西,直到我能找到自己的观点!)

相反,你可能会把用户体验视为项目中的一切之王. 这是一个有价值的目标,但让我讲我的第二个故事.

几年后,上述项目取得成功, 我的一个同事来找我,让我通过自动化一些有时会出现的混乱的现实场景来优化UX, 这样只要点击一下就能解决问题. 我开始分析是否有可能设计出一种算法,因为这个场景中有许多奇怪的边缘情况,所以不会出现任何误报或误报. 我和同事聊得越多, 我就越意识到这些要求根本不会得到回报. 这种情况只偶尔出现一次——每月一次, 比如说,一个人花了几分钟才解出来. 甚至 if 我们可以成功地自动化它, 没有任何bug, 需要几个世纪的开发和维护时间才能从我的同事节省的时间中得到回报. 我这个讨人喜欢的人很难说“不”,但我不得不缩短谈话时间.

因此,让计算机尽其所能帮助用户,但只能在一定程度上. 你怎么知道那是什么程度呢?

对于计算机来说,什么是容易的,什么是困难的

我喜欢采用的一种方法是分析用户体验 比如你的开发人员分析他们的代码. 从你的用户那里找出他们花最多时间一遍又一遍地点击或输入相同内容的地方, 看看你能否优化这些互动. 您的代码能否对最有可能输入的内容做出一些有根据的猜测, 把它设为无输入默认值? 除了某些禁止的上下文(不单击EULA确认)?),这确实会对用户的工作效率和幸福感产生影响. 如果可以的话,做一些走廊可用性测试. 有时, 你可能很难解释什么是容易的,什么是不容易的,但总的来说, 这个值对你的用户来说可能非常重要.

避免过早优化:何时以及如何优化

尽管我们对其他环境进行了探索,现在让我们明确地假设我们正在优化 某些方面 本文其余部分的原始机器性能. 我建议的方法也适用于其他目标, 喜欢的灵活性, but each target will have its own gotchas; the main point is 那 prematurely optimizing for 任何东西 可能会失败.

那么,在性能方面,有哪些优化方法可以遵循? 让我们开始吧.

这不是草根倡议,这是三重eh

TL;DR是: 从上往下工作. 更高级的优化可以在项目的早期进行, 低级别的应该留到以后再用. That’s is all you need to get most of the meaning of the phrase “premature 优化”; doing things out of this order has a high probability of wasting your 团队’s time 和 being counter-effective. 毕竟,您不会从一开始就用机器代码编写整个项目,不是吗? 所以我们的AAA 做法 是按照这个顺序进行优化:

  1. 体系结构
  2. 算法
  3. 组装

人们普遍认为,算法和数据结构往往是最有效的优化领域, 至少在性能方面是这样. 记住, 虽然, 这种体系结构有时决定了可以使用哪些算法和数据结构.

我曾经发现了一个软件,它通过对每笔财务交易多次查询SQL数据库来生成财务报告, 然后在客户端做一个非常基本的计算. 小型企业在使用该软件几个月后,即使他们相对较少的财务数据也意味着, 拥有全新的桌面和相当强大的服务器, 报告生成时间已经长达几分钟, 这是他们需要经常使用的. 最后,我编写了一个包含求和逻辑的简单SQL语句——通过将工作转移到服务器以避免所有的重复和网络往返,从而挫败了它们的体系结构——甚至在数年之后还保存了价值连年的数据, 我的版本可以在相同的旧硬件上在几毫秒内生成相同的报告.

有时,您对项目的体系结构没有影响,因为在项目中进行体系结构更改已经太迟了. 有时候你的开发人员可以像我在上面的例子中所做的那样绕过它. 但是如果你在一个项目的开始,并且对它的架构有一定的发言权, 现在是优化的时候了.

体系结构

"If builders built buildings the way programmers wrote programs, 然后第一只来的啄木鸟就会毁灭文明." --Weinberg's Law

在一个项目中, 体系结构是事后更改成本最高的部分, 这就是为什么一开始就进行优化. 如果你的应用是 通过鸵鸟传递数据, 例如, 你会想把它构造成低频的, 高负载数据包,以避免使糟糕的瓶颈变得更糟. 在这种情况下, 你最好有一个完整的《欧博体育app下载》来娱乐你的用户, 因为一个装载旋转器是不能解决问题的. (开玩笑:几年前,我安装了我的第一个Linux发行版,Corel Linux 2.0,并且很高兴长时间运行的安装过程包含了这个. 在看过很多次Windows 95安装程序的广告屏幕后,我已经记住了它们, 这在当时是一股新鲜空气.)

作为架构变更代价高昂的一个例子, 前面提到的SQL报告高度不可伸缩的原因从它的历史中可以清楚地看出. 随着时间的推移,这款应用也在不断发展, 从起源于MS-DOS和一个本土的, 最初甚至不是多用户的自定义数据库. 当供应商最终切换到SQL时, 模式和报告代码似乎已经被一一移植了. 这给他们留下了多年的印象,000%以上的性能改进,洒在他们的更新, 每当他们有机会完成架构转换时,就会在给定的报告中实际利用SQL的优势. 跟我当时的雇主那样的锁定客户做生意是件好事, 显然,在最初的转换过程中,要优先考虑编码效率. 但在某些情况下,满足客户的需求就像锤子拧螺丝一样有效.

架构部分是关于预测您的项目需要能够扩展到什么程度, 在哪些方面. 因为建筑是非常高级的, 如果不将我们的关注点缩小到特定的技术和领域,我们很难得到具体的“做什么和不做什么”.

我不会这么说,但其他人都这么说

值得庆幸的是, 互联网上到处都是收集到的关于各种建筑的智慧. 当您知道是时候优化您的体系结构时, 研究陷阱基本上可以归结为找出描述你的辉煌愿景的流行语. 很有可能有人和你有同样的想法, 试过, 失败的, 迭代, 并将其发表在博客或书中.

仅通过搜索来识别流行语可能很棘手, 因为对于你们所说的FLDSMDFR, 其他人已经创造了SCOPWWHWTT这个术语, 它们描述的是你正在解决的同一个问题, 但是用的是完全不同的词汇. 开发者社区的救援! 在StackExchange或HashNode上找到尽可能详细的描述, 加上你的建筑的所有流行语 不是,这样他们就知道你做了充分的初步研究. 有人会很乐意开导你的.

与此同时, 一些一般性建议 可能是很好的思考食物.

算法与汇编

给定一个有利的架构,这里是 程序员 你的团队会得到最多的T-bling. 避免过早优化的基本原则也适用于此, 但是您的程序员最好考虑这个级别的一些细节. 当涉及到实现细节时,有很多事情需要考虑 我写了一篇关于面向一线和高级编码人员的代码优化的单独文章.

但是一旦你和你的团队实现了一些性能方面未优化的东西, 你真的把它放在 不要这样做? 你 从来没有 优化?

你是对的. 下一条规则是,仅限专家使用, 不要这样做 然而,.

基准测试时间!

你的代码可以工作. 也许它太慢了,你已经 知道 您将需要进行优化,因为这些代码将经常运行. 也许你不确定,或者你有一个O(n)算法并且认为它可能是好的. 不管是什么情况, 这个算法是否值得优化, 在这一点上我的建议是一样的:运行一个简单的基准测试.

为什么? 很明显,我的O(n³)算法不可能比其他任何算法都差? 有两个原因:

  1. 您可以将基准添加到您的测试套件中, 作为你绩效目标的客观衡量标准, 不管他们现在是否得到满足.
  2. 即使是专家也会在不经意间让事情变慢. 即使看起来很明显. 真的 明显的.

第二点别相信我?

如何从1400美元的硬件中获得比7000美元的硬件更好的结果

Jeff Atwood的StackOverflow名声 曾经指出 有时(通常)是可以的, 在他看来,购买更好的硬件比把宝贵的程序员时间花在优化上更划算. OK, 因此,假设您已经得出了一个合理的客观结论,即您的项目符合这种情况. 让我们进一步假设您要优化的是编译时间, 因为你正在做的是一个庞大的Swift项目, 这已经成为一个相当大的开发者瓶颈. 购买硬件的时间!

你应该买什么?? 很明显,相对而言,更贵的硬件往往比更便宜的硬件表现得更好. 所以很显然, a $7,000 Mac Pro应该比一些中档Mac Mini更快地编译你的软件, 正确的?

错误的!

事实证明有时 更多的内核意味着更高效的编译……在这种特殊情况下, 领英(LinkedIn)经历了惨痛的教训后发现,对于他们的业务堆栈来说,情况正好相反.

但我看到管理层犯了一个更大的错误:他们甚至没有对前后进行基准测试, 他们发现,硬件升级并没有让他们的软件“感觉”更快. But there was no way to 知道 for sure; 和 further, 他们仍然不知道瓶颈在哪里, 所以他们仍然对业绩不满意, 已经用完了他们愿意分配给这个问题的时间和金钱.

好的,我已经做过基准测试了. 我真的可以优化吗? 然而,??

是的,前提是你已经决定要这么做了. 但也许这个决定要等到更多/所有其他算法也实现了, 所以你可以通过分析看到运动的部分是如何组合在一起的,哪些是最重要的. 这可能是在一个小应用程序的应用程序级别,或者它可能只适用于一个子系统. 无论哪种方式,记住,一个特定的算法可能看起来对整个应用程序很重要,但是 即使是专家——尤其是专家——也容易误诊.

三思而后行

“我不知道你们怎么想,但是……”

来自硅谷的Gavin Belson说, "I don't wanna live in a world where someone else makes the world a better place...比我们做得更好."

作为最后的思考食物, 考虑一下如何将错误优化的理念应用到更广阔的视野中:你的项目或公司本身, 甚至是一个经济部门.

我知道, 人们很容易认为科技会拯救世界, 我们可以成为实现这一切的英雄.

再说,就算我们不做,别人也会做.

但请记住,权力会导致腐败,尽管出发点是好的. 我不会在这里链接到任何特定的文章, 但如果你没有遇到任何, 我们有必要了解一下破坏经济的更广泛影响, 有时这最终会服务于谁. 您可能会对试图通过优化来拯救世界的一些副作用感到惊讶.

附言

你注意到什么吗,擎天柱? 我唯一一次叫你擎天柱是在开始的时候现在是在结束的时候. 整篇文章都没叫你擎天柱. 说实话,我忘了. 我写了整篇文章都没叫你擎天柱. 最后,当我意识到我应该回过头来,把你的名字撒在整篇文章里, 我心里有个小小的声音说, 不要这样做.

了解基本知识

  • 什么是过早优化?

    尝试优化时,第一次编码. 在任何给定时刻,最好从最高级别进行性能优化. 对于绿地项目,在架构阶段. 对于遗留项目, 经过适当的分析来识别瓶颈, 而不是玩昂贵的猜谜游戏.

  • 为什么过早优化不好?

    假设(假定的)性能优化代码实际上是您的首要任务,这是一个隐藏的陷阱, 上面的正确性, 清晰, 可测试性, 等等....... 另一个陷阱是假设所讨论的代码对整体性能有足够的影响,值得进行优化. 过早的优化对双方都不利.

标签

聘请Toptal这方面的专家.
现在雇佣
凯文·布洛赫

凯文·布洛赫

验证专家 在工程
8 的经验

Bergerac、法国

2017年1月31日成为会员

作者简介

Kevin拥有超过20年的全栈、桌面和独立游戏开发经验. 他最近专门研究PostgreSQL、JavaScript、Perl和Haxe.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

专业知识

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

Toptal开发者

加入总冠军® 社区.