- 资讯
- 软件
- 博客
- 专区
- 问答
- 活动
- 工具
- 培训
- 众包
- APP
- Gitee
性能优化是代码中最大的威胁之一。
你可能在想,又有人在这么说了。我能理解。从字面意思可以明确地判断,任何类型的优化都是好事,所以你想把它学好是件很自然的事情。
不要脱离大家,认为自己是更好的开发者。不要避免变成 日常 WTF 中的 “Dan”,因为你相信代码优化是正确的事情(Right Thing to Do™)。在工作中你会为此喊到自豪。
计算机硬件越来越快, 软件制作越来越容易,但任何你希望做到的简单的事情最后总是会花更长的时间,你因此而摇头(顺便说一句,这种现象称为 Wirth 定律),决心顺其自然。
你真是高尚,但别再这样了。
无论你在编程方面有多么丰富的经验,你这样做都是在严重阻碍自己的目标。
怎么会这样呢?让我们回到主题。
首先,什么是代码优化?
通常我们在定义它时,都假设我们希望代码有更好的性能。我们会说通过编写或重写代码,达到尽可能减少使用内存或磁盘空间,或最大限度减少 CPU 时间或网络带宽,或者尽可能少的使用额外核心的目的。
实际上,我们有时候会默认另一个定义:编写更少的代码。
但是以此为目标首先写出来的的代码往往成为别人的眼中钉。谁的眼中钉?可能是下一个需要理解你代码的倒霉蛋,甚至可能就是你自己。像你这样聪明能干的人其实可以避免自毁:保持目标,但重新评估你做事的方法,就算它们在表面看起来没有问题。
所以代码优化现在还是一个模糊的术语。我们会在下面考虑一些其它优化代码的方法。
我们先来听听高人的建议,一起探索 Jackson 有名的代码优化规则:
不要这样做。
(仅对专家而言!) 仍然不要这样做。
我要从一个相当尴尬的极端例子开始。很久以前的一段时光,我正在涉足精彩的、鱼与熊掌不可兼得的 SQL 世界。问题是,那时我踩到了蛋糕却再也不想吃掉它,因为它湿了并且开始闻起来像臭脚。
我正在涉足精彩的、鱼与熊站不可兼得的 SQL 世界。问题是,那时我踩到了蛋糕…
请稍等。让我从我打的这个比方中恢复过来,并解释一下。
那时我正在为一个内部网应用程序做研发,我希望将来有一天它能成为所工作的小公司的完全集成的管理系统。 它将为他们跟踪一切,而不像他们当时运行的系统,它不会丢失数据,因为它将由 RDBMS(关系型数据库管理系统)支持,而不是其他开发人员使用的不可靠的、自产的、扁平的文件。我想从一开始就把各种东西设计得尽可能智能,因为我有一块空白的石板。对于这个系统的想法在我的脑海中像烟花一样爆炸,我开始设计表 - 给客户关系管理(CRM)的联系人表和他们的许多上下文的变化的表,会计模块,库存,采购,内容管理系统(CMS),以及项目管理, 这个系统我很快就会自己试用。
所有这一切都停顿下来,朝开发和性能的方向,你猜对了,因为要优化。
我看到,对象之间(表示为表的行)在现实世界中可以有许多不同的关系, 我们可以从跟踪这些关系中获益:我们可以保留更多地信息,并最终将业务分析自动化到所有地方。鉴于这是一个工程问题,我做了一个似乎是对系统灵活性的优化。
在这一点上,重要的是要注意你的脸,因为我不会被追究责任,如果你的手掌打了你的脸。准备好了吗?我创建了两个表:relationship 及其有外键引用到的 relationship_type。relationship 可以指向整个数据库中的任意两行,并描述它们之间的关系的性质。
哦,伙伴!我刚刚优化了灵活性,该死地太多了。
实际上太多了。现在我有一个新问题:给定的 relationship_type 自然在每个给定的行组合之间都不会有意义。虽然一个人能通过与公司之间的雇用关系使得这变得有意义,但是这在语义上是绝对不能对等的。比如两个文档之间。
我们将只向 relationship_type 添加两列,指定可以应用哪个表。 (如果你已猜想我想通过将这两列移动到一个引用 relationship_type.id 的新表来实现这一点,那么给你加分,这样做可以在语义上应用于多个表的关系,而无需重复表名。因为如果我需要更改表名,但忘记在所有适用的行中更新,这会导致 Bug 的产生!后患无穷。)
幸运的是,在沿着这条路走了一段之后,我在一条线索风暴中被无意地打醒了。当我醒来时,我意识到我已经或多或少地设法重新实现了 RDBMS 的内部的外键相关表。通常,我喜欢在大功告成的时刻,大喊“我是超神了”,但遗憾的是,各位,这并不是我要说的优化方法之一。 忘记这个失败的设定——这个设定带来的膨胀差点毁了我的简单应用程序的后端,它的 DB 几乎没有任何测试数据,几乎不可用。
让我们退后一步,看看这里的许多衡量标准中的其中两个。一个是灵活性,这是我的既定目标。在这种情况下,我的优化本质上是建筑性的,甚至还不成熟:
(我将在我即将发表的文章中提到,“多云,有过早优化的机会”)然而,我的解决方案却因过于灵活而失败。另一个度量标准,可伸缩性,是我甚至还没有考虑过的,但这样至少免去了可能发生的附带的损害。
没错,“心好累”。
这对我来说是一个很好的教训,让我知道了优化是如何完全失败的。我的完美主义彻底崩溃:我的聪明使我产生了我所做过的最客观、最不明智的解决方案之一。
当你在拥有工作原型和测试套件以证明其正确性之前,倾向于重构,考虑下将这种冲动引导到其他方向。Sudoku 和 Mensa 是个不错的选择的,但也许一些实际上直接使你的项目受益的东西会更好:
安全性
运行时稳定性
清晰度和编码风格
编码效率
测试有效性
性能剖析
你的工具包/ DE
DRY(避免重复代码)
但要留意:优化这些特定任务之一都可能需要其他任务的代价来实现。至少,这是以时间为代价的。
在这里,很容易看到写代码中多少存在一点艺术。对于上述任何一种,我可以告诉你有关太多或太少被认为是错误选择的故事。谁在这里思考也是上下文的重要组成部分。
例如,关于 DRY:在一个工作中,我接手了至少 80% 冗余语句的代码库,因为它的作者显然不知道如何和何时写一个函数。其他 20% 的代码是令人困惑的自相似。
我的任务是增加一些功能。在所有要实现的代码中都需要重复一个这样的功能,并且未来的任何代码将必须仔细的复制以利用新功能。
显然,只有为了我自己的头脑清楚(高价值)和任何未来的开发者才需要去进行重构。但是,因为我是将新的代码加入代码库,我首先写了测试,进行回归测试,以确保我任何的重构没有问题。事实上,只是这样做:我遇到两个错误,我不会注意到生成所有冗繁而费解的脚本输出。
最后,我以为我做得很好。在重构之后,我用一些简单的代码行实现了被认为是一个难点的功能,使我的老板印象深刻。而且,程序性能总体上提高了一个数量级。但不久之后,同一位老板告诉我,我进度太慢了,而且这个项目应该早就完成了。(潜台词:编码效率是优先考虑的问题。)
注意:优化任何特定的[方面]将以牺牲其他方面为代价。至少,这是以时间为代价的。
我仍然认为我的选择是正确,即使当时代码优化没有得到老板的赞赏。没有重构和测试,我想事实上可能要花更长的时间才能找到正确的路,也就是说,专注于编码速度实际上会阻碍它的发展。(嘿,那是我们的主题!)
与我在我做过的一个小型项目工作相比。在项目中,我尝试了一个新的模板引擎,并希望从一开始就养成良好的习惯,尽管尝试新的模板引擎并不是项目的最终目标。
我注意到,我添加的几个代码区域非常相似,而且每个区域需要指向同一个变量三次,DRY警铃在我的脑海中响起,我开始试图用模板引擎来找到正确的方法做事情。
事实证明,经过几个小时的无结果的调试之后,我发现这个模板引擎不可能像我想象的那样。不仅没有完美的解决DRY;根本没有任何一个解决方案!
我试图调整自己的价值观,我完全破坏了我的编码效率和幸福感,因为这条弯路导致我的项目花费了我那天可能取得的进步。
即使这样,我完全错了吗?有时,值得一点投资,特别是在新的技术背景下,要更早地了解最佳实践,而不是稍后。减少代码重写和撤销的坏习惯,对吧?
不,我认为即使在我的代码中寻找减少重复的方法也是不明智的,这与我在以前的处事中的态度形成了鲜明的对比。原因是场景是一切:我在一个小型项目中探索一个新的技术,而不是长期解决。一些额外的线路和代码重复不会伤害任何人,但失去专注,伤害了我和我的项目。
等等,所以寻求最佳做法可能是一个坏习惯?有时。如果我的主要目标是学习新的引擎,或者普通的学习,是很花费的时间的:修修补补,找出约束,通过研究发现不相关的功能和问题。但我忘了这不是我的主要目标,这让我付出了代价。
这是一种艺术,就像我说的。而这种 开发的艺术受益于提醒,不要这样做。至少让你考虑在工作时有哪些是有的价值,在你的工作场景中哪些又是最重要的。
那第二条规则呢?什么时候才能够进行优化?
好的,无论是你还是别人,当架构被设置好,数据流被考虑清楚并文档化,就可以开始编码了。
让我们把"不要这么做"扩展下:不要进行编码。
这听起来像是提前优化,但和别的优化不一样,这个非常重要。是为了避免可怕的 NIHS 或“Not Invented Here”综合征 - 假设你的优先级包括代码性能和最小化开发时间。如果没有,如果你的目标完全以学习为导向的话,可以跳过下一节。
有人会自以为是地 重新发明方形车轮,就算像你我一样的诚实谦虚的人,也会因为认识的不全面而犯这样的错误。了解堆栈中每个 API 和工具的每个选项,并且随着它们的发展深化知识,做到与时俱进,这当然是需要很多工作的。但是,这段时间的投入能帮你成为这个领域的专家,让你避免像 CodeSOD 上的人一样,做各种无用的尝试。
评论删除后,数据将无法恢复
玻璃钢生产厂家新乡玻璃钢座椅生产厂家日照玻璃钢外壳厂家直销白银玻璃钢休闲椅哪家好榆林玻璃钢树池坐凳公司泉州玻璃钢花盆加工包头玻璃钢公仔雕塑安顺玻璃钢座椅厂家直销阳泉玻璃钢休闲椅多少钱桂林玻璃钢外壳批发昭通玻璃钢花盆多少钱盐城玻璃钢花钵生产厂家漳州商场美陈定做黄冈玻璃钢医疗外壳厂抚州玻璃钢花箱定制萍乡玻璃钢装饰厂眉山玻璃钢装饰造型公司南京玻璃钢景观雕塑厂家聊城玻璃钢设备外壳定制渭南玻璃钢天花吊顶批发黄冈玻璃钢茶几生产厂家广州玻璃钢动物雕塑厂家直销临汾玻璃钢造型定制揭阳玻璃钢沙发哪家好曲靖玻璃钢垃圾桶定制贺州玻璃钢装饰工程批发玉溪玻璃钢动物雕塑定制孝感玻璃钢景观雕塑厂家直销湖南玻璃钢花坛厂家直销宁波玻璃钢机械外壳厂家上海不锈钢雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤
评论(4)
但是数月后问题出现了 我看到自己的代码就像在看java的api 逻辑本应该很连贯的 现在却被拆分的支离破碎 我不得不重新理清思路(记忆力差,没加注释也是个问题) 也算是个教训吧 适当的优化重构代码 不要过度 就像设计模式一样 不要为了设计而设计 也不要为了优化而优化