程序员今天如何“微优化”?[关闭]


14

回到“好日子”,当我们将共享软件复制到软盘上供朋友使用时,我们还使用了一些汇编程序。有一种常见的“微优化”实践,您会凝视组装线,直到找到一种方法来用更少的指令来表达它。甚至有句谚语在数学上是不可能的:“ 您总是可以再删除一条指令。 ”鉴于如今,对于大多数(大多数)编程而言,通过小的常数因子来更改运行时性能已经不是主要问题,程序员正在转移这些微型代码。其他地方的优化工作?

换句话说,可以将最佳实践带到不再增加任何价值的极端状态吗?而是在浪费时间吗?

例如:程序员是否浪费时间推广只能从一个地方调用的私有方法?是否浪费时间减少了测试用例数据?程序员(仍然)过分担心减少代码行吗?

下面是我要寻找的两个很好的例子:(1)花时间找到正确的变量名,甚至重命名所有内容;(2)删除甚至是次要和脆弱的代码重复。


请注意,这与“ 您针对什么进行优化? ” 问题不同,因为我要问的是其他程序员似乎想最大化使用什么,这些问题的耻辱是“微”优化,因此不能有效地利用时间。



@Macneil,我不知道其他程序员会进行哪些微优化,但是我没有太多时间这样做。我的同事们也很忙(仅2美分)。
Job

@Job:您从未见过有人在浪费时间,无缘无故更改代码?认为自己很幸运。下面有两个很好的例子:变量名和次要代码重复。
Macneil 2010年

1
按照目前的说法,这个问题是一个改进。我无法取消近距离投票,但几天后它将消失。实际上,这个问题吸引了一些很好的答案。
罗伯特·哈维

1
顺便说一句,任何最佳实践都可以发挥到极致,以至于不再产生价值。
罗伯特·哈维

Answers:


22

代码格式化

Don't     get    me   wrong             ,
code      should be   consistent        & 
readable                                , 
but       some   take it         too far.

是的,好的旧变量类型和变量名称在一系列变量声明中需要它们自己的列。哦! 忘记了的额外行=和初始化程序的第四行!
Macneil 2010年

[该死,会投票,但达到了我的每日限额...]
Macneil 2010年

3
我们的教授强迫我们以这种方式为外出作业设置代码格式。花了我多年摆脱这个习惯。
奥利弗·韦勒

噢亲爱的。在其他答案上,我在笑,但是这个答案确实很伤人:-(
Steve314,2010年

2
+1我曾经在一个图书馆工作过,那里的开发人员拒绝将他的代码修改为const-correct,因为它弄乱了他的列格式代码...
Dean Harding 2010年

20

过去,我经常写很多汇编器。不仅仅是编译器变得更好,还在于大多数硬件现在都有大量逻辑专门用于乱码执行。真正的微问题是调度,大多数计算机指令需要几个机器时钟才能产生结果-错过缓存的内存负载可能要花费数百个!因此,其想法是安排其他指令执行有用的操作,而不是等待结果。而且现代机器可以在每个时钟周期发出几条指令。一旦我们开始乱序执行硬件,我发现尝试通过手动编码获得出色的性能成为了杯赛。首先,乱序的硬件将不会按照您精心设计的顺序执行指令,新颖的硬件架构降低了软件调度不理想的负担,以至于编译器通常只占性能的百分之几。我还发现,编译器现在正在实现众所周知但复杂的生成技巧,例如展开,底层加载,软件管道等。最重要的是,您必须非常努力地工作,跳过其中一些技巧,编译器就会击败您。全部使用它们,所需的汇编指令数量将增加几倍!

甚至更重要的是,大多数性能问题不是关于指令发出率,而是关于将数据输入CPU。如上所述,内存等待时间现在是数百个周期,CPU可以在每个时钟周期执行几条指令,因此,除非对程序(尤其是数据结构)进行了设计,以使高速缓存命中率极高,请对该指令进行微调级别将没有收益。就像军人说的那样,业余爱好者在讲战术,专业人士在讲物流。现在,绩效编程已超过90%的物流(移动数据)。这很难量化,因为现代内存管理通常具有多个高速缓存级别,并且虚拟内存页面由称为TLB的硬件单元处理。地址的低位对​​齐也很重要,因为实际的数据传输不是以字节为单位,甚至64位long-long,但是它们以缓存行为单位。然后,大多数现代计算机都具有可预测不久的将来可能需要的高速缓存行未命中的硬件,并发出自动预取以将其放入高速缓存中。因此,现实情况是,在现代CPU中,性能模型非常复杂,几乎无法理解。即使是详细的硬件仿真器也无法匹配芯片的确切逻辑,因此完全不可能再进行精确调整。

仍然有一些手动编码的地方。数学库(例如exp函数)以及更重要的线性代数运算(例如矩阵乘法)通常仍由为硬件供应商(例如Intel或AMD或IBM)工作的专家手动编码,但它们可能仅每个大型计算机公司需要几个顶尖的汇编器程序员。


1
对于CPU供应商以外的人员来说,手工编码正变得越来越困难,因为该任务越来越依赖于内部知识和特定于供应商的工具(编译器和分析器)。spiral.net尝试对CPU优化进行建模,并自动搜索最佳解决方案。
rwong

许多计算机语言通过使使用双精度计算进行计算(其结果将呈现为)成为一种痛苦,从而促使程序员进行无意义的微优化float。由于某种原因,我无法理解,许多人认为这是一件好事。
2014年

10

我有时会花时间(浪费时间)来为变量或方法选择一个好名字,这样它不仅可以准确地描述语言,而且还具有良好的语言风格。

当我尝试将整个作品(一个程序)置于相同的语言风格时,它会走得更远。有时,我的观点会发生变化,因此我会对此书进行修订。:)

不,它需要那么多时间。相当罕见。但是我喜欢在程序中保持良好的语法。


3
命名很难。因此,当您想到一个更好的名称时,应该重构名称。请注意,这可以吸引您的精力,并且希望也可以明确“为什么”。

1
这非常左脑(大脑的左侧负责处理语言)。作为一个头脑敏捷的程序员,我倾向于花费更少的时间来关注语义,而花费更多的时间来关注所有部分如何组合在一起。
杰森·贝克

7
变量和方法命名是可维护性的重要组成部分。人们应该花时间思考名称,以便从现在起5年后,维护代码的人可以更轻松地使用它。
GrandmasterB

@grandmaster:完全同意。
罗伯特·哈维

4
@ right-brainers:请为lef-tbrainers编写代码,这样我也可以阅读您的代码
Juan Mendes 2010年

10

时间复杂度。我花了太多时间优化事情,以使最坏情况的性能比我所知道的程序会遇到的数量级大几个数量级。

我实在太痴迷了,尽管即使其他设计决策无法将其实际发生,也不能放过它,但它可能会变得那么大。

但是,以我的辩护,如果不切实际的事情变成现实,那么优化实际上不再是“微观的”。注意,我并不是说不可能,而是不切实际的

当然,需求优先。


1
因为这个原因,我在一家下陷的公司工作。
亨利

2
@亨利-我保证,不是我:)
蒂姆·波斯特

1
@亨利:你的意思是说,他们浪费时间优化可能永远不会发生的事情,或者他们没有考虑可能永远不会发生的事情……直到它们确实发生并且为时已晚?
院长哈丁2010年

2
@亨利:如果一家公司拥有高度可扩展的产品并且仍然沉没,那是销售和营销的错(因为没有针对大批量的客户并且定价不当),而不是开发的错。
rwong 2010年

1
当没有一个用户的情况下,该公司花费大量时间为数百万个用户设计系统。一定是营销错误。是的,我们责怪营销,那些家伙是白痴。
亨利

8

我想我浪费了数周的时间来摆弄Java异常处理程序。

对于每年两次或三次失败的代码,这是很多工作。这是警告还是信息?错误或致命?在5分钟内重新生成该过程真的致命吗?如果一切仍处于默认状态,这真的是一个警告吗?

大量的肚脐注视着和有关IO错误性质的讨论。如果您无法通过网络读取文件,是文件错误还是网络错误?等等。

某一时刻,我用所有concat字符串替换了该字符串,String.format以便年度文件错误不会在堆中导致多余的对象。那真是浪费。


3
这是重要的工作。失败的代价=每天WTF上都会显示您的错误消息。
2010年

7

我想我对LOC太多了。LOC本身不是很多,而是语句的数量甚至更多的重复语句。我对重复的代码过敏。总的来说,我喜欢重构,但是我想我做的事情中约有50%不会使代码明显更好。


4
为“我对重复代码过敏” +1。另请参见我的答复这里:programmers.stackexchange.com/questions/14610/...
麦克尼尔

考虑一下-我遇到了与循环有关的问题,循环涉及Knuth关于goto的观点,有时为了编写结构化代码,必须交易一个或两个或一些重复的代码。在极少数情况下(最常见=生成的代码),我使用goto,但是这种混乱的变化使我浪费时间,不停地尝试循环以消除琐碎的效率,同时又使代码保持可读性。
2010年

5

逐行读取文件,而不是将整行读取为一个字符串并一次处理该字符串。

当然,它会影响执行速度,但很少值得花额外的代码行。它使代码的可维护性大大降低,并增加了代码大小。

是的,如果文件的大小为3GB,但大多数文件不是那么大(至少不是我正在使用的文件;-),这可能没有任何意义。


3
即使大于或等于3GB,64位计算机也可以使用虚拟内存来处理它。使用内存映射文件,它甚至在需要时都不会读取文件的任何部分。请注意,在正常情况下,即使是微优化。
2010年

3

当我编写汇编语言时,合理选择字节和周期是很有意义的,但是那是很久以前的事,从那时起编译器已经走了很长一段路。我现在不会尝试手动进行优化。

同样,当我改用C编写代码时,要比C编译器做得更好,这是很容易的,但是每年Borland或Microsoft或某人都会发布一个新的'n改进的版本,从而使以前的版本更加完善。我开始关注编译器发出的实际汇编代码,如果它没有编写一些美观而紧凑的代码,展开循环,在循环外移动变量等,便会感到惊讶。

现在,我正在使用许多高级语言(如Perl,Python和Ruby)进行编写。我先使用了一些编译器技巧,例如有意义的循环展开,将静态变量移入循环等,但我对此并不担心,因为现在CPU速度更快了。如果某个应用似乎在意外拖动,那么我将使用探查器并查看可以找到的内容,然后,如果可以改进某些地方,我将开始基准测试各种我认为可以更快执行的方式,然后看看它如何扩大规模。

通常,根据多年的经验,我会尝试在编写代码方面保持精明。


嗨,格雷格,感谢您的回答,但是我正在寻找程序员在浪费时间而不是在优化运行时性能方面所做的事情。上面有两个很好的例子:变量名和删除次要的代码重复。
Macneil 2010年

3

微观优化:提高可并行处理的事物的单线程性能,或者可以使用新硬件简单地对其进行改进。

如果10年前的计算机运行缓慢,那么更便宜的解决方案可能是购买更新,更快的计算机,而不是浪费程序员的时间进行优化。不过,考虑的优化重点应该是找到一种方法来使用您今天可以获得的8个内核,或者几年后可以获得的64个内核,而不是像垃圾那样浪费大量的细节。采集。


2

就运行时性能而言,微优化即使在今天也不是一个封闭的问题(尽管可能不那么普遍)。我有时不得不向人们解释,每个请求分配一个额外的对象或添加一个额外的函数调用的开销可以忽略不计。

除此之外,我还看到程序员为简单起见进行了微优化(包括我自己)。我尚未在某个地方工作,而不必解释简单性与简单性之间的区别。


为什么是程序员。有什么不同吗?请有什么区别。
Dan Rosenstark 2010年

@Yar-程序员为何与其他人有所不同?
杰森·贝克

为什么会programmers.= programmers.stackexchange.com是从每一个地方有什么不同,你已经工作,在那里你必须解释这两个概念之间的区别?请说明不同之处。
Dan Rosenstark 2010年

@Yar-我不知道那样。实际上,由于程序员.se的目的是帮助程序员汇集知识,所以我希望这样做不是为了使人们至少对我的回答有所启发。
杰森·贝克

2
那么,b / t的简单性和简单性有何不同?
Dan Rosenstark 2010年

2

除非确实必要,否则我全力以赴。我全力以赴。原则上,我只会优化将产生所需差异的内容。

这是原则上的。但是原则是骗子。

我习惯于照顾经常使用的库中的函数,我认为这些函数会在内部循环中大量使用。然后,当您在另一个函数中发现某些东西时,这种情况就很少使用了...

哦,然后是“我正在编写它-当然,这是一个重要的库”逻辑。

哦-顺便说一句 我从未使用过探查器来指导优化。没有商业渠道,也从来没有建立起gprof的动机。

基本上,我是伪君子。这些原则适用于其他人,但是我非常害怕有人说“但是,为什么要用这种缓慢而cr脚的方式写它?” 因此我永远无法真正将它们正确地应用于自己。

不过,我并不像我在这里所说的那样糟糕。而且我完全不会自欺欺人,所以你知道我是对的!

编辑

我应该补充-我的主要愚蠢的挂断之一是通话开销。当然,并不是到处都可以,但是在那些我认为会在很多内部循环情况下使用的情况下(我没有客观证据表明存在问题)。我编写了讨厌的基于offsetof的代码,以避免多次调用虚拟方法。结果甚至可能更慢,因为它可能不是优化器旨在处理的一种编码风格,但是它更聪明 ;-)


+1啊,是的!该类解析我的应用程序的高度特定和古怪的命令行参数,但是让我在Javadoc时格式化并完整记录它,因为肯定其他人会使用它多年![稍后需要投票,达到我的每日上限。]
Macneil 2010年

@Macneil-那是Doxygen,我知道。使用每个选项,我都可以打开,因此每个小功能都会详尽地“记录在案”,并附带许多漂亮的GraphViz图形。确实可以帮助每个人理解我的代码的重要性-打印输出可以为很大的办公楼铺上墙纸。
史蒂夫314

1

在过去,计算机的时钟时间以微秒为单位,内存以千字节为单位,并且使用原始编译器,微优化在某种意义上是有意义的。

当前计算机的速度和大小以及当前编译器的质量意味着微优化通常是浪费时间。当您绝对必须从一些计算密集型代码中获得最高性能时,或者您正在为资源极其有限的嵌入式系统编写程序时,就有例外了。

但是我正在寻找程序员在浪费时间而不是在优化运行时性能方面所做的事情。

Twitter和Facebook浮现在脑海:-)


嗨,斯蒂芬,这是关于微优化的很棒的评论,但是您看到现代的等效方法吗?(Facebook和Twitter并不是“最佳实践”,可以
推广

还是有道理的。时钟时间可能要小
几个

@Stuart-这意味着要进行微优化的代码要多得多,这根本无法扩展。
Stephen C
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.