我为什么要关心微观性能和效率?


71

C / C ++页面上的许多问题和答案,特别是或间接地讨论了微性能问题(例如,间接函数,直接函数与内联函数的开销),或者使用O(N 2)vs O(N log N)算法100个项目列表。

除非或直到我知道我有问题,否则我始终不关心微性能,也不关心宏性能,而是专注于易于维护的可靠代码。

我的问题是,为什么很多程序员这么在乎呢?对于大多数开发人员来说,这真的是一个问题吗?我是否只是幸运地不必为此担心太多,还是我是一个糟糕的程序员?


5
+1,很好的一般性问题。
iammilind

+1好问题。.我添加了2个标签。.希望您不要介意。

2
我引用了两个引号:1)“过早的优化是万恶之源。” 2)80%的时间将花费20%的代码(80/20规则)。
James Khoury

2
我注意到有关我的O(n * n)示例的几个答案。我明确指定了100个项目的列表,但他们仍然坚持认为O(nlogn)更好,并明确指出如果该列表将来达到1000或100万个,则性能将得到改善。这种微优化是不是因为程序员正在针对可能的未来需求而不是实际的当前需求进行编程?(我之前在哪里听说过……)
马腾兹

5
@James Donald Knuth的全部话是:“我们应该忘记效率低下的问题,大约有97%的时间是这样:过早的优化是万恶之源”。关于该线程中剩余的3%,会有一些很好的答案。
StuperUser 2011年

Answers:


14

实际上,性能很少是需要在该详细级别上进行管理的问题。如果您知道将要存储和处理大量数据,则应密切注意这种情况,但是否则,您是对的,并且要更好地保持简单。

最容易陷入的陷阱之一-尤其是在具有如此细粒度控制的C和C ++中-太早进行优化并且水平太高了。通常,规则是:A)在发现问题之前不要进行优化,并且B)不要通过使用探查器来优化尚未证明是问题区域的任何内容。

B)的推论是:众所周知,程序员在预测其性能瓶颈在哪里方面很糟糕,即使对于一个人来说,他们也很擅长。使用分析器,优化速度较慢的部分,或者如果多次调用某段代码,则更改算法,从而导致问题。


6
另一个:执行一次的初始化代码通常不需要优化,因此请转到其他地方。
迈克·德西蒙

3
取决于“一次”的频率。在运行时./configure,我敢说,多达75%的运行时间可能花费在脚本运行的程序中的“初始化”代码上。25-50%甚至可能花费在动态链接上。
R.,

12
规则A是一个可怕的规则。系统的体系结构在性能中起着重要的作用,如果以后再发现您的体系结构根本无法满足您的性能要求,那么您基本上就被搞砸了。因此,尽管您可以忽略一些细节,但一开始就完全忽略这一点是完全错误的。
edA-qa mort-ora-y

3
@ edA-qa:我曾经这样认为,但是多年来,在没有任何性能考量成为关注点之前,经历了更多的项目挣扎或失败。每当我遇到性能问题时,此修复程序的成本都相对较低,只需几天或几周,就比其他“错误”检测到开发中的某个修复程序引起的关注更多。但是,就像其他风险项目一样,需要在项目早期识别并缓解性能上的麻烦。
mattnz

5
OP询问了为什么要这么多地关心,并且我看不到该回复实际上如何回答了这个问题,除非OP对听到某人说“不用担心!”更感兴趣。
红尘

54

我认为您列表中的所有内容都是微优化,通常不应该关注它,除了

在100个项目列表上使用O(n * n)vs O(NlogN)算法

我认为应该加以考虑。当然,该列表现在有100个项目,并且对于小n来说一切都很快,但是我愿意打赌,相同的代码将重新用于几百万行的列表,并且代码仍将具有合理地工作。

选择正确的算法绝不是微优化。您永远不会知道两个月或两年后将使用相同代码的哪种数据。与在分析器的指导下易于应用的“微优化”不同,算法更改通常需要进行大量重新设计才能有效利用新算法。(例如,某些算法要求输入数据已经被排序,这可能迫使您修改应用程序的重要部分以确保数据保持排序)


36
为“选择正确的算法永远不会进行微优化” +1。

9
我也为此+1,但是请注意,当您确定数据大小较小时,选择big-O-optimum算法可能不利于开发时间,程序大小,甚至内存使用情况。如果要对扑克牌进行分类,您是否真的要编写快速排序,平滑排序或合并排序?我将从简单的插入排序开始,或者使用排序网络。
R.,

8
那很好笑。在有关微优化的主题中,许多评论员对答案进行了微优化。;)
确保

5
“我愿意很快打赌,相同的代码将重新用于几百万行列表中”:这完全取决于问题域。示例:如果您正在编写象棋算法,则可以合理地确定棋盘尺寸不会改变。如果您为自动驾驶汽车编程,那么车轮的数量也不会那么快。
尼基,

3
我不喜欢“选择正确的算法绝不是微优化”,因为考虑到“正确”一词的本质,它显然是正确的。但是,我觉得您的意思实际上是“最快或最高效”的算法,我不同意这种算法。如果要花费大量时间来实施并且该段的速度或空间几乎无关紧要,则选择最有效的算法是错误的选择。
Casey Patton

18

很久以前,在我的第一份工作中,我为嵌入式系统编写了代码。这些系统使用8086微处理器,并且内存有限。我们使用了Intel C编译器。我构建的一个系统需要访问3-d结构数组。就像书中告诉我的那样构建它:调用3个维度的malloc,然后为下一个维度分配行,然后为末端节点分配calloc。

这非常复杂(当时对我而言),我必须进行曲线拟合,ANOVA过程控制和卡方分析。没有图书馆为我们做到这一点;我们必须全部编写并将其全部安装到8086上。

该系统像狗一样运行。快速分析之后,我发现最大的问题之一就是分配器。为了解决这个问题,我放弃了对malloc的所有调用,而是对一个大内存块进行了自己的内存管理。


在同一工作的另一种情况下,客户抱怨其统计过程控制系统的响应时间。我之前的团队设计了“软件PLC”系统,操作员可以使用布尔逻辑来组合信号和跳闸开关。他们用一种简化的语言来编写它,今天我们称之为“领域特定语言”。我记得它看起来像((A1 + B1) > 4) AND (C1 > C2)这样。

原始设计在每次评估时都会解析并解释该字符串。在我们微不足道的处理器上,这消耗了大量时间,这意味着流程控制器无法像流程运行一样快地进行更新。

我重新审视了它,并决定可以在运行时将该逻辑转换为汇编代码。我对它进行了一次解析,然后每次运行时,该应用都会调用到动态生成的函数中。我猜想就像今天的某些病毒一样(但我不是很清楚)。结果是性能提高了100倍,这使客户和我的老板真的很高兴。

由于我已经构建了一个自定义编译器,因此新代码几乎没有可维护性。但是性能优势远胜于维护劣势。


最近,我正在开发一个需要动态解析XML动态的系统。较大的文件将花费更多时间。这对性能非常敏感。解析太慢会导致UI完全无法使用。

这些事情总是出现。


所以....有时您需要可维护的,易于编写的代码。有时,您希望代码能够快速运行。权衡是您需要对每个项目做出的工程决策。


9
在所有示例中,事后对其进行优化的成本并不比一开始就编写快速代码高得多。因此,首先编写较慢的简单代码,然后在需要的地方进行优化对所有这些代码都有效。
CodesInChaos 2011年

6
@CodeInChaos:答案没有其他要求。它谈到了OP的问题“为什么我应该关心微观性能和效率?” 预优化问题只是由其他答复者推断出来的。
webbiedave 2011年

12

如果要处理大图像并遍历每个像素,则性能调整至关重要。


2
+1 –以及高频财务,任何类型的音频/视频编码器/解码器,模拟和建模(例如游戏),系统范围的位(例如CPU调度程序和内存管理器等)
Billy ONeal

3
CAN是至关重要的,但IS你已经证明了它之后是如此关键只你异形它是在那里你觉得问题。(提示:它可能不存在。)
我的正确想法是

2
@正确的观点:实际上,对于图像处理,数据处理通常是第二大时间消耗者(I / O仍然是最大的)。但是,针对I / O进行优化需要大量不寻常/疯狂的设计,并且需要其他程序员的认可,有时甚至根本无法改进。然而,处理部分通常可尴尬地并行化,因此它们很容易获得收益。(一个人的调整可能会被另一个人视为直接的教科书实现……除非您达到VirtualDub的级别)
rwong 2011年

12

让我告诉您有关文化背后原因的一些信息。

如果您接近40岁而不是20岁,并且一直在为成年人谋生,那您就已经成年了,那时C ++确实是城里唯一的游戏,台式机应用是常态,而硬件仍然在带宽/性能方面大大落后于软件。

  • 我们曾经不得不做一些愚蠢的编程技巧才能读取大型(> 2G)文件...
  • 我们曾经担心可执行文件的大小 ...
  • 我们曾经担心程序会消耗多少内存...
  • 我们定期做出算法时间与空间权衡的决定...
  • 即使在后端,我们必须用C或C ++编写CGI程序来处理任何体面的问题。RPS的速度…… 快了几个数量级
  • 我们过去经常在delphi / c ++ / vb之间对性能优劣进行测试!

少数人有今天担心这些事情。

但是,十年前,您仍然需要担心您的软件是通过56kb的调制解调器下载的,并在运行5年的PC上运行的。您还记得1996年的PC多么糟糕吗?考虑一下4GB硬盘,200Mhz处理器和128Mb RAM ...

而10年前的服务器呢?戴尔的“下一代”服务器售价为2000美元,并配有2个(!)1Ghz奔腾处理器,2Gb或Ram和20Gb硬盘。

这只是一场不同的比赛,所有拥有10年经验的“高级”工程师(这些家伙很可能会回答您的问题)在那种环境下cut之以鼻


1
额外的20年经验也意味着我们已经经历了很多次优化过程,并且避免做以后可能需要的事情。出于同样的原因,我在使用锤子时不会拍打拇指。
Blrfl 2011年

1
循环展开<shudder>
红尘

5
今天,所有认为带宽,CPU和内存不受限制的孩子都发现他们的移动应用程序不能很好地工作。
gbjbaanb

9

这里已经有10个答案,有些真的很好,但是因为这是我的个人宠儿...

过早的优化a)比简单的解决方案要花更多的时间b)引入更多的代码,其中简单的解决方案只有一半的大小和一半的复杂度,并且c)绝对不应该让可读性降低。但是,如果开发人员可以在使用std :: map或std :: vector之间进行选择,并且出于纯粹的无知而选择了错误的集合,则其性能甚至不如过早的优化那样糟糕。如果您今天可以稍稍更改代码,保持可读性,保持相同的复杂性,但使其效率更高,该怎么办呢?还是您称其为“过早优化”?我发现很多人甚至都不会以任何一种方式思考。

我曾经是一个建议“微优化”的人,只需要很少的改动,而我得到的反馈与您刚才说的一样,“您不应该过早地进行优化。让我们开始吧,我们将对其进行更改。如果出现性能问题,请稍后”。我们修复了几个版本。是的,这是一个性能问题。

尽管早期的优化可能不是很好,但是我认为如果人们在编写代码时了解代码将要做什么,而不是简单地忽略任何导致O(x)表示为“优化”的问题,这将非常有益。您现在可以编写很多代码,而对性能的一点思考就可以避免80%的问题。

还请考虑,您的环境中不会立即发生许多性能问题。有时候,您会有一个客户来限制,或者另一个开发人员决定在您的框架之上进行构建,并将对象数量增加10倍。尽管现在有了一些有关性能的信息,您以后可以避免进行非常昂贵的重新设计。而且,如果在软件正式发布后发现问题,那么即使是简单的修复,其使用成本也要贵20倍。

因此,总而言之,随时注意表现有助于养成良好的习惯。与编写简洁,尽可能简单和组织化的代码一样重要。


+1:对于聘用开发Shrinkwrap软件和商业网站的人员来说,这是可雇用性因素之一。预防要比客户的诅咒便宜。
rwong 2011年

6

我怀疑您看到的很多都是简单的采样错误。当人们处理简单的情况时,他们编写代码,这就是结局。他们在处理相对棘手的问题时会提出问题,例如需要优化,尤其是在不一定明显需要优化的情况下。

就是说,无疑也涉及一些过早的优化。正确与否,C和C ++在性能方面享有盛誉,这往往会吸引那些关心性能的人们-包括那些可能因为真正需要而尽可能多地为获得乐趣而进行优化的人。


1
+1-注意:大多数带有“性能”标签的SO问题可能都是该采样错误的一部分:P
Billy ONeal,

3
我肯定在这里看到了很多该有的过早优化问题……我认为这是由于许多业余程序员开始写游戏的想法,而且还有大量的废话“优化”书籍和与游戏开发相关的网站,使初学者难以接受。:-)
R..11年

4
当您要处理棘手的问题时,通常可以轻松地从棘手的问题中休息一下,而不必担心您是否应该使用i++或花费时间++i
Carson63000,2011年

@ Carson63000:是的,这可能会完全歪曲样本。或者他们花时间回答关于为什么我operator ++没有编译的问题。
rwong

4

其他两个答案都提到了嵌入式系统,我想对此进行扩展。

例如,有许多包含低端处理器的设备:您家中的锅炉控制器,一个简单的袖珍计算器或现代汽车中的数十个芯片。

为了省钱,这些闪存可能具有大量的闪存(用于存储代码)和RAM,对于那些仅为PC或智能手机编写代码的用户而言,它们显得微不足道。为了节省功率,它们可以以相对较低的时钟速率运行。

举个例子,STM32系列微控制器从24 MHz,16 KB闪存和4 KB RAM120 MHz,1 MB闪存和128 KB RAM

当为此类芯片编写代码时,如果您希望使代码尽可能高效,则可以节省大量时间。显然,过早的优化仍然不是一个好主意。但是通过实践,您将学习如何快速和/或用最少的资源解决常见问题,并相应地进行编码。


1
我自己工作的一个领域,就是嵌入式系统的好点子。即使考虑到这一点,我多年来的经验仍然是误导性优化始终是浪费时间。没有指导我们的工具,我们很少会发现问题所在
Jeff

2

这些本质上是低级语言,当一个人遇到一种病理表现情况时,一个无关紧要的细节在99%的时间内引起瓶颈,实际上,一个人有机会直接解决该问题(与其他大多数人不同)语言);但是当然,通常,如何立即最有效地执行操作尚不明显。因此,这里有一半的奇怪/有趣的微观优化问题被问到。

另一半来自那些对它们与金属的接近程度感到好奇的人。毕竟,这些本质上是低级语言。


+1:值得指出的是,“病理表现”可能发生在世界上任何人,无论使用何种语言或平台。以较低级别的语言重新实现以进行测试和读取反汇编的功能可能会提供更多的见解,但并不总是提供可行的解决方案。示例:“我知道我可以在汇编中完成它-但它需要在部分信任环境中运行!”
rwong

2

在使用C和C ++时,性能始终是一个热门话题。关于应该走多远,您总是可以疯狂地达到内联ASM的地步,或者使用指针算法来加快迭代速度。但是,有一点指向人们花费大量时间进行优化,以至于开发整个程序的工作就停止了。

处理这些问题时,需要考虑程序员的性能和代码的性能。这些重点放在哪一个总是会提出有趣的问题。最后,最重要的问题是它对用户的吸引力。用户是否将使用创建具有数百或数千个元素的数组的数据?在这种情况下,为使事情快速完成而进行的编码可能会使您的用户抱怨程序的标准操作很慢。

然后就是将要处理少量数据的用户。如果您使用的高级功能使您更容易进行维护,而牺牲了一些性能,那么在这里和那里的一些文件,诸如排序和文件操作之类的操作对于用户而言就不会那么明显。

这只是您将遇到的问题的一个小例子。其他事项包括目标用户的硬件。如果您要处理嵌入式系统,那么您将不得不担心更多的性能,例如,如果您的用户使用的是具有ram内存的双核计算机。


嗯。我不使用指针算法来实现更快的迭代-无论您使用的是基于索引的迭代还是基于指针的迭代,它都是每个循环的乘法和加法指令。我确实使用它,因为它通常比基于索引的迭代更清晰。
Billy ONeal,

指针算术不比w / e快。

2

为什么程序员这么在乎呢?有一些愚蠢的想法充斥着他们的头脑,例如在他们知道自己拥有性能问题之前就解决了性能问题,而在猜测时却不理解。

这很棘手,因为根据我的经验,应该提前考虑一些性能问题。需要经验才能知道它们是什么。

也就是说,我使用的方法与您的方法相似,但不相同:

  1. 从最简单的设计开始。特别是,数据结构应尽可能规范化并尽可能减少。在某种程度上,它具有不可避免的冗余性,因此应该避开通知,以使其保持一致。更好的是容忍暂时的不一致,并通过定期的过程进行修复。

  2. 在开发程序时,请定期进行性能调整,因为性能问题可以悄悄地悄悄蔓延。我使用的方法是随机暂停,因为我认为这是最好的。

这是我的意思的一个例子


1

老实说,这取决于您的目标,以及您是专业编程还是业余爱好。

如今,现代计算机确实是功能强大的机器。无论您决定执行什么基本操作,无论您是否尝试进行微优化,它们都可以使他们的工作非常快。但是,当然,如果您要执行其他操作(例如,针对物理或化学等领域的超级计算),则可能需要根据需要进行尽可能多的优化。

早期的MIT程序员并非天生就制作出很棒的东西。他们开始简化和增强现有算法。他们的骄傲是使2 + 2的得分比现有算法少四分之二(这只是一个例子,您知道了)。他们不断尝试在TI-83机器中使用更少的打孔卡来提高性能。

另外,如果您正在为嵌入式系统编程,那么您当然必须关注微性能。您不希望慢速的数字时钟比另一个数字时钟的时间慢5纳秒。

最后,如果您是一个业余程序员,那么即使程序速度很快,优化最小的细节当然也没有害处。不需要它,但是可以肯定的是您可以从事一些工作,并有机会学习更多。如果您是专业从事某款软件的开发人员,那么除非非常需要,否则您将无法获得如此奢华。


1
我不认为作为业余程序员与这无关。仅仅因为您没有专业地做某事,并不一定意味着您有很多时间在这上面花费。而且,大多数业余爱好者会犯比大多数真正专业人士更大的错误,例如选择错误的算法。此外,专业人员可能正在开发一种产品,该产品处理的数据量比业余爱好者要多得多(因此必须更快),并且必须使客户对应用程序的性能感到满意。业余爱好者没有这种限制。
比利·奥尼尔

他们没有,但是他们确实有更多的时间仅在他们愿意的情况下进行工作。

3
我会反驳。我每天有8个小时或更长时间从事专业工作。我的业余爱好项目每天获得1个,也许每天2个小时。
比利·奥尼尔

1

在100个项目列表上使用O(N2)vs O(NlogN)算法。

我最近也有类似情况。我有一系列物品。在预期的情况下,列表中有两个(!)项目,即使在最坏的情况下,我也不希望超过四个或八个。

我需要对该列表进行排序。原来,用std::sort排序网络(实际上是很多嵌套的ifs)代替可以节省很大一部分运行时间(我不记得这个数字了,但是大约是10%到20%)。这是微优化的巨大优势,并且代码绝对对性能至关重要。

当然,我只是分析后才这样做。但是要点是,如果我使用的语言像C ++一样不方便且令人费解(更不用说其用于重载解析的极其复杂的规则),那么我想获得全部好处。


1

累积能源消耗

在这些讨论中,我一直认为缺少一个答案,这使我有点累加了能源消耗

当然,如果您使用高级解释语言编写程序,并使其在具有几层间接层的浏览器中运行,或者循环所用的时间是0.01秒而不是0.001秒,那么也许没什么大不了的。没有人会注意到,也就是说,没有个人用户会注意到。

但是,当在某些情况下成千上万甚至数百万个用户使用您的代码时,所有这些额外的低效率加起来了。如果您的工具每天仅阻止CPU进入睡眠状态10秒钟,并且有100万用户使用它,那么效率低下的算法每天仅会消耗140 kWh [1]

我很少讨论这个问题,我认为这很可悲。我强烈怀疑,对于流行的框架(如Firefox)和精美的交互式Web应用程序,这些数字要差得多,这将是一个有趣的研究。


[1]我只是用一千万秒乘以50瓦来弥补这一点。确切数字取决于很多事情。


1
您应该从提到魔术字“ mobile”开始。当在桌面平台上运行时,一个需要1/100秒的CPU时间每秒绘制一帧60次的应用程序将“足够快”。将性能提高十倍,对用户的影响将为零。但是,在移动平台上,以90%的CPU利用率运行的应用程序可能比10%的运行速度快得多。
超级猫

1

有时,您所拥有的算法不能比线性时间更好,而线性时间仍然需要强大的性能。

一个示例是视频处理,在不循环遍历每个像素的情况下,您不能使图像/帧更明亮(作为一个基本示例)(嗯,我想您可以使用某种层次结构来指示子级继承的属性,这些属性最终会下降到图像块中对于叶节点,但是您将需要花费更高的成本循环遍历每个像素到渲染器,并且即使是最优化的图像过滤器,代码也可能难以维护)。

在我的领域中有很多这样的案例。与受益于任何复杂数据结构或算法的线性复杂度循环相比,我倾向于做更多的线性复杂度循环,这些循环必须涉及所有内容或读取所有内容。当必须触摸所有内容时,没有可以跳过的工作。因此,在这一点上,如果您不可避免地要处理线性复杂性,则必须使每次迭代完成的工作越来越便宜。

因此,在我的情况下,最重要和最常见的优化通常是数据表示和内存布局,多线程和SIMD(通常按此顺序排列,其中数据表示最重要,因为这会影响执行后两者的能力)。我没有遇到太多问题,这些问题可以通过树,哈希表,排序算法以及类似的东西来解决。我的日常代码更像是“为每件事做某事”。

当然,讨论何时需要优化(更重要的是不需要优化),微处理算法是另一种情况。但是在我的特殊情况下,如果关键执行路径需要优化,则通常可以通过微级优化(如多线程,SIMD以及重新布置内存布局和访问模式以提高引用位置)来实现10倍以上的速度提升。我很少会说用Introsort或radix排序替换冒泡排序,或者用BVH替换二次复杂性冲突检测,而发现热点可以从热/冷场拆分中受益。

现在,在我的情况下,我的领域对性能至关重要(光线跟踪,物理引擎等),以至于缓慢但完全正确的光线跟踪器(要花费10个小时来渲染图像)通常被认为是无用的,或者比完全互动但快速的光线跟踪器更为有用。输出最丑陋的图像,由于缺少水密射线/三重交点,射线泄漏到处。速度可以说是此类软件的主要质量指标,可以说甚至比某种程度上的正确性还高(因为“正确性”是光线追踪的模糊概念,因为所有事物都是近似的,只要它不会崩溃或类似的东西)。在这种情况下,如果我不考虑预先的效率,我发现我实际上必须在最昂贵的设计级别上更改代码以处理更高效的设计。所以如果我不

游戏是与我相似的另一个领域。如果您的游戏像幻灯片一样以每秒1帧的速度运行,那么游戏逻辑的正确性或代码库的可维护性和出色的设计都无所谓。在某些领域,缺乏速度实际上会使应用程序对其用户无用。与游戏不同,在光线追踪等领域没有“足够好”的指标。用户始终希望获得更高的速度,而工业竞争主要是在寻求更快的解决方案。除非它是实时的,否则它将永远不够好,届时游戏将使用路径跟踪器。然后对于VFX来说可能还不够好,因为从那时起,美术师可能想加载数十亿个多边形,并以30+ FPS的速度对数十亿个粒子之间的自碰撞进行粒子模拟。

现在,尽管如此,尽管如此,我仍然使用脚本语言(Lua)编写了大约90%的代码,而无需担心性能。但是我有异常大量的代码,实际上确实需要遍历数百万至数十亿的事物,而当您遍历数百万至数十亿的事物时,您的确会注意到天真的单线程代码之间的巨大差异,每次迭代都会调用一个高速缓存未命中,比方说,矢量化代码在并行访问连续块中运行,在连续块中没有无关的数据加载到高速缓存行中。


0

正如您所提到的,在解决由这些问题真正引起的某些问题之前,关心微性能问题是毫无价值的


0

总的来说,真的不可能回答这个问题。当今正在构建的大多数软件都是内部网站和LOB应用程序,对于这种编程,您的推理是非常正确的。另一方面,如果您正在编写设备驱动程序或游戏引擎之类的东西,则没有优化是“过早的”。您的软件可能会在具有不同硬件限制的完全不同的系统上运行。在这种情况下,您应该针对性能进行设计,并确保不要选择次优算法。


正是我想说的。每个软件都有其应用程序域,不应期望其在其外部具有最佳性能。从这个意义上讲,过早的优化是误导完美主义的一个例子。
K.Steff

0

我认为非常关心性能的程序员的问题是,有时在他的一生中,他需要编写微性能代码,也许非常紧急,并且他学会了,学到了很多东西,最后他知道了很多事情和技巧。

现在,很难忘记,并且无需事先测量即可显示出他不需要担心,他使用快速代码站在安全的一面。

展示自己的深厚知识,技能和一些技巧,并重用您学到的东西,总是很高兴的。它使您感到很有价值,花时间在学习上,值得。

有时,在我的生活中,我了解到前缀增量更快...

for (int i = 0; i < MAX; ++i)

...比后缀增加:

for (int i = 0; i < MAX; i++)

现在,如果MAX为低,则没有关系,如果循环中有实际工作,也将无所谓。但是,即使今天的编译器自行优化代码,也没有理由使用postfix版本。

寻求性能的人可能除了编写“工作代码”(例如“工作和可读代码”)外,还需要一个额外的目标,以便在众多选择中获得指导。


0

我是否有幸不必为此担心太多,还是我是一个糟糕的程序员?

您关心您的要求吗?如果性能不是必需的,那就不用担心。花大量的时间对您的雇主不利。

在一定程度上,性能始终是必需的。如果您可以不考虑它就打它,那么您就可以不考虑它。

就个人而言,当我的测试需要很长时间才能通过时,我通常会受到性能的驱动。我太急躁,无法等待5分钟才能通过一组测试。但这通常可以通过摆弄测试来解决。

我的问题是,为什么很多程序员这么在乎呢?对于大多数开发人员来说,这真的是一个问题吗?

有大量的程序员在乎他们的关心程度是有道理的。有很多人不是。让我们来谈谈那些不是。

在使事物真正起作用之后,程序员在学校学习的第一件事就是大O表示法。他们中的许多人都正确地学习了这一课,因此适当地专注于受n极大影响的事物。其他人则不懂数学,而只是取而代之的是,它必须很快就可以运用。更糟糕的是,这些学生中的一些人除了使代码正常工作并使其快速运行之外,再也没有学到任何关于代码重要的事情。错过的课程:使其可读性强,设计精良,无缘无故地玩耍。

克努斯是对的:过早的优化是万恶之源。但是一旦奏效,下一步是什么?快吧?没有!下一步是可读的。可读是第一步,下一步,中间步骤和最后一步。我发现许多执行不必要的性能优化的人正在总线下提高可读性。

有些人甚至因其代码的可读性而感到不快。他们不得不苦苦寻找难以理解的其他人创建的代码,所以现在轮到他们来回收投资了。

我知道这一点,因为我曾经这样做过。如果结构精简到难以理解的单行布尔表达式,我曾经将一条完全可读的5行重构,并自豪地将其发送给我的教授,期望给我留下深刻的印象,因为我可以创建出如此紧凑而令人生畏的东西。我没有得到我想要的赞美。

如果代码保持可读性,则使以后快速变得容易。这就是为什么Knuth强调“过早”而不是“不需要”的原因。因为可以肯定,越快越好。但是更好只有更好,这取决于您为此付出了什么。因此,请等到知道真正需要的性能后再为此做出牺牲。牺牲可读性很勉强,因为一旦它消失了,就很难找回。

超越可读性的是整个软件设计领域。这个网站是关于什么的。有些人不知道如何设计。因此,由于他们不能给设计留下深刻的印象,所以会造成难以理解的混乱,因此人们无法说出自己毫无头绪。既然没有人修复过他们的代码,那一定是好的代码吧?

对于某些人来说,性能是抓住一切做任何事情的借口。程序员具有很大的权力和自主权。他们之间已经有了信任。不要滥用信任。

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.