在现代计算时代,在“典型业务应用程序”中-为什么性能很重要?[关闭]


29

对于某些人来说,这似乎是一个奇怪的问题。

我是一名业余Java程序员。我已经开发了几个游戏,一个可以创建音乐的AI程序,另一个用于绘画的程序以及类似的东西。这是要告诉您,我有编程经验,但是没有业务应用程序的专业开发经验。

我在这个网站上看到了很多有关性能的话题。人们经常争论什么是C#中执行任务的最有效算法,或者为什么Python速度慢而Java速度更快等。

我想了解的是:为什么这很重要?

在某些特定的计算领域中,我明白了性能为何如此重要:游戏,在一个恒定更新循环中每秒发生成千上万次计算,或者其他程序所依赖的低级系统,例如OS和VM等。

但是对于普通的,典型的高级商务应用程序,为什么性能很重要?

我能理解几十年前为什么如此重要。计算机速度慢得多,内存也要少得多,因此您必须仔细考虑这些事情。

但是今天,我们有太多的可用内存可供使用,并且计算机是如此之快:如果特定的Java算法为O(n ^ 2),这实际上有关系吗?对于这个典型的商业应用程序的最终用户而言,这实际上会有所不同吗?

在现代计算的当今时代,当您在典型的业务应用程序中按GUI按钮并在后台调用O(n ^ 2)算法时,您实际上是否感到效率低下?

我的问题分为两部分:

  1. 在实践中,今天的业绩对典型的正常业务计划是否重要?
  2. 如果是这样,请给我提供此类应用程序中性能和优化很重要的位置的真实示例。


如果性能很差,性能很重要。
2014年

Answers:


40

没错,业务应用程序中的性能并不是大多数程序员讨论它的方式真正重要的主题。通常,我从程序员那里听到的与性能有关的讨论有几个问题:

  • 它们大多是过早的优化。通常,有人希望“最快的方式”进行无明显原因的操作,最终要么改变大多数编译器都会做出的代码更改(例如,用乘法替换除法或内联方法),要么花几天时间进行更改这将有助于在运行时获得几微秒的时间。

  • 他们经常是投机的。我很高兴在Stack Overflow和Programmers.SE上看到与性能相关的问题时经常提到概要分析,但是当我看到两个不知道概要分析性能的程序员时,我也感到失望。他们应该在代码中进行的相关更改。他们相信这些更改将使一切变得更快,但实际上每次更改都不会产生可见效果或放慢速度,而探查器会将其指向易于优化的代码的另一部分,浪费了80%的时间。

  • 它们仅专注于技术方面。面向用户的应用程序的性能与感觉有关:它感觉快速,响应迅速,还是感觉缓慢又笨拙?在这种情况下,用户体验设计师通常可以更好地解决性能问题:简单的动画过渡通常可能是感觉非常慢的应用程序和感觉响应的应用程序之间的区别,而两者都需要花费600毫秒。做手术。

  • 它们基于主观因素,即使它们与技术约束有关。如果不是感到快速响应的问题,那么应该有一个非功能性要求,该要求指定在特定系统上运行的特定数据应执行多快的操作。实际上,情况更像是这样:经理告诉他发现缓慢的东西,然后,开发人员需要弄清楚这是什么意思。是像“应该低于30毫秒,而现在却浪费了十秒”中那样缓慢,还是像“我们可以将持续时间从十秒降低到九秒”中那样缓慢?

在作为程序员的职业生涯的早期,我为许多客户开发了一款软件。我坚信该软件是下一个伟大的事物,它将为世界带来幸福,因此我显然对性能感到担忧。

我听说过诸如“概要分析”或“基准”之类的术语,但我不知道它们的意思,也不会在乎。此外,我太专注于阅读有关C的书,尤其是讨论优化技术的章节。当我发现计算机执行乘法运算的速度比除法运算快时,我会尽一切可能用乘法代替除法。当我发现调用方法可能很慢时,我尽可能地组合了很多方法,就好像以前的100个LOC方法已经不是问题。

有时,我整夜都在做一些更改,这些更改使我确信,这是一个没人要的慢速应用程序与每个人都想下载和使用的快速应用程序之间的区别。我对两个对这个应用程序感兴趣的实际客户要求实际功能的事实并没有打扰我:“如果应用程序运行缓慢,谁会想要一个功能?”

最后,只有两个客户停止使用该应用程序。尽管我付出了所有努力,但运行速度并不出奇,主要是因为当您不知道索引是什么并且您的应用程序是数据库密集型时,出现了问题。无论如何,当我只做另一个与性能相关的更改时(每月使用一次的代码执行速度提高了几微秒),客户看不到更改。他们所看到的是,用户体验很糟糕,缺少文档,他们几个月来要求的关键功能不在这里,而且要解决的错误数量也在不断增长。

结果:我希望这个应用程序可以被世界上成千上万的公司使用,但是今天,您将不会在互联网上找到有关该应用程序的任何信息。仅有的两个客户放弃了它,该项目也被放弃了。它从未销售过,也从未公开发布过,今天,我什至不确定我是否可以在PC上编译它(也找不到原始资源)。如果我将更多的精力放在真正重要的事情上,这不会发生。

话虽如此,性能总体上很重要

  • 在非商业应用中,它变得至关重要。有嵌入式软件,在服务器运行的软件(当您每秒有数千个请求时,这不是很大,性能开始成为问题),在智能手机视频游戏专业软件上运行的软件(尝试处理)在Photoshop中使用不是很快的机器就可以存储50 GB的文件),甚至是出售给很多人的普通软件产品(如果Microsoft Word花费两倍的时间来进行每次操作,则损失的时间乘以数量用户数将成为一个问题)。

  • 在商业应用中,有许多情况下,这些应用程序的感觉,并慢会被用户所痛恨。您不想要那样,就可以根据您的顾虑来提高绩效。


4
很好的答案,尤其是因为将重点放在无意义的性能讨论和无意义的优化上。
布朗

1
a simple animated transition may often be the difference between an app which feels terribly slow and the app which feels responsive-尽管一定要谨慎使用,但对于每天乱扔动画和过渡效果的应用程序,如果每天盯着这些过渡效果,可能会感到沮丧!
Cosmic Ossifrage

您的报价来源是什么?
亚当·约翰斯

1
@AdamJohns:没有消息。引用了我自己的文章草稿,这些文章尚未在我的博客上发布。
2014年

@MainMa太棒了。我真的很喜欢你的观点。
亚当·约翰斯

44

是。是的,它确实。运行时速度不是您应该唯一关心的问题,它没有像1982年那样紧迫,也没有像在低功耗嵌入式系统上那样紧迫,但是它始终是一个问题,理解这一点很重要为什么会这样。

首先,您提到的渐进复杂度描述了程序随着输入大小的增长而发生的行为。一个处理10个项目的非线性程序可以避免做多余的工作,但是当您一天要处理1000个项目时,它会咬住您,因为它不仅会变慢,而且会变慢很多。而且,在达到100,000个项目之前,您不知道(没有广泛的分析和基准测试)该点是100个项目,1000个项目还是不。可能难以置信,但是,理所当然地选择最佳算法比为每个例程估计这一点并根据此估计选择实现要容易得多。

另外,请阅读用户体验基础知识。有经过严格研究的阈值,这些阈值决定了如何根据程序的响应时间(10ms,100ms,几秒钟等)来感知与程序的交互。超过这些阈值之一将导致用户与您的应用程序脱离联系,除非您处于编写人们必须使用的垄断软件的快乐位置,否则脱离联系的用户会直接转化为负业务价值,因为这会导致客户流失。

这些仅仅是为什么专业程序员必须了解算法复杂性并负责任地处理它的几个原因。如今,除非事实证明它是时间紧迫的内部循环,否则通常不必费力地编写特别优化的,可读性很差的代码,除非事实证明这是时间紧迫的内部循环,但您永远都不应调用比明显必要的复杂性高的类做这项工作。


2
在算法选择时要记住的另一件事:由于库和抽象,已经为您或至少在“幕后”进行了很多算法选择。您仍然应该知道它们对性能的影响。而性能确实很重要
joshin4colours 2014年

14

是的,它确实!

自从您询问示例以来,每天都会想到几种情况:

  1. 处理大数据:许多业务应用程序都由数据库支持,并且在许多情况下,这些数据库会溢出数据。而且由于驱动器空间便宜,因此记录和存储的数据量非常大。就在上周,一位客户抱怨说,当只显示一些平均数(查询超过几百万行...)时,他的应用程序太慢了-在日常使用中,我们还会进行批处理数据转换和计算,并且运行时数以万计小时。去年,算法优化使一批处理的时间从8个小时减少到4个小时,现在它不再与日班工作冲突了!

  2. 响应能力:曾经进行过可用性研究(如果有时间,我会在ux.se上添加到相关问题的链接...),用户满意度与响应能力密切相关。200ms与400ms的响应时间之间的差异很容易使您花费很大一部分客户,而您却留给了竞争对手。

  3. 嵌入式系统:计算机并没有变得越来越快,它们越来越慢并且越来越小^ _ ^移动开发对应用程序开发产生了巨大的影响。当然,我们可以像现代台式计算机上的果冻豆一样抛出内存和CPU周期,但是现在您的老板要求您在freakin手表或SIM卡上实现睡眠分析算法。


4

在实践中,今天的业绩对典型的正常业务计划是否重要?

我不知道什么是典型的正常业务程序。我所知道的是,最终用户总是会向我们的程序提供比我们计划更多的数据(通常是在询问程序的大小并增加安全余量之后),在这种情况下,他们期望线性增加运行时,接受log n行为,并抱怨在发生任何其他情况时应用程序冻结。并且他们倾向于考虑结果的大小,而不是考虑输入的大小,除非从从其 POV看出必须处理所有输入数据。

因此,是的,至少在复杂性级别上,性能至关重要。复杂性类中的微优化实际上并不重要,除非您明显比竞争对手差(在某些市场中是基准测试,或者是凭原始的看法-在“瞬时”更改类,“不是立即进行,但用户不会“不要切换到其他内容”,“足够慢以使用户切换到其他内容,有可能中断操作流程”,“足够慢以使用户启动任务然后不时检查”,“足够慢用户计划在午餐,夜晚,周末期间启动任务”)。


4

在现代业务应用程序中,性能问题并非以缺少CPU或内存的形式出现。但是它们以网络等待时间,I / O性能和抽象的形式隐藏了所有这些。这完全取决于设计的质量和开发人员的经验。如果它只是一次从数据库中拖出一行而不是运行查询,那么即使是简单的CRUD应用程序也可能会停止运行(也称为N + 1问题)。

问题是拥有好的设计和经验丰富的开发人员会很昂贵。而且,激怒用户通常比投资于实际性能优化要便宜得多。在某些情况下,客户将需要高性能(例如,Web浏览器),但是很少将它们应用于常见的业务应用程序。


3

请记住,对于基于服务器的应用程序,您可能有成百上千,甚至数百万的用户试图同时执行操作。在这种情况下,效率的少量节省可能会对服务请求所需的硬件数量产生重大影响。


5
实际上,通过将更多的硬件投入到该问题上,可以更好地解决大多数恒定因素,因为通常,更多的硬件要比花费更多的时间优化事物更便宜。问题在于不良的渐进(缩放)行为,因为抛出更多的硬件对此无济于事。
Jan Hudec

3
您只需要优化一次,但是您每个月都要支付电费。
Jaydee 2014年

2
@JanHudec:当您当前所在的网站(我们亲爱的Stack Exchange)在全球25个服务器上每月提供5.6亿次页面浏览量时,我真不敢说真的。
Mehrdad 2014年

2
@Mehrdad:他们本可以用C编写它,也许可以在20台服务器上运行,而不是在25台服务器上运行。但是他们没有这样做,因为节省的钱不会超过增加的开发时间。许多Web服务都是使用Python和PHP(通常使用的最慢的语言)来实现的,但没有人想到以任何更快的速度重写它们,因为增加的开发时间将无法获得回报。在大多数情况下,只需添加更多硬件即可解决常数因素。缩放(渐近)问题是另一回事。
Jan Hudec

3
...而且,公平地讲,数据库(这是大部分艰苦的工作)正在编写和优化中,以便快速运行。
Blrfl 2014年

3

这当然很重要。

主要问题甚至不在于使用户烦恼,例如,当GUI元素被重绘两次或三次(在集成图形上确实很重要!)时,会经历不必要的延迟,或者仅仅是因为程序需要很长时间才能完成……无论如何确实(主要是无趣的东西)。当然,这也是一个问题。

存在三个重要的误解:

  1. 大多数典型的商用计算机并没有“功能强大得多”。典型的商用计算机不是带有踢屁股图形卡和16GB RAM的8核i7。这是一台笔记本电脑,带有中级移动处理器,集成显卡,2GB主内存(如果幸运的话,为4GB),5400RPM磁盘和企业版Windows,在企业版Windows中运行各种实时防病毒和策略执行软件背景。或者,对于大多数顾问而言,“计算机”就是iPhone。
  2. 大多数“典型的业务用户”不是技术人员,他们不理解创建具有10-12个交叉引用选项卡,150列和30,000行的电子表格的含义(这些数字并不像您想象的那样不切实际!),他们也不想知道。他们会做到的。
  3. 一秒钟的损失并没有付出代价,这是一个公然错误的假设。

我的妻子在这种“典型的商业环境”的高端工作。她正在使用的计算机花费的工作时间约为3.5个小时。在良好的一天中,启动Microsoft Outlook大约需要3分钟(直到服务器准备好时,季度末需要6-8分钟)。提到的某些3万行电子表格中的某些要花2-3秒的时间来更新“冻结”计算机的值(更不用说Excel花费多长时间才能启动并首先打开它们!)。共享桌面时更糟。甚至不让我继续使用SAP。
十万人是否每个工作日损失20-25分钟,什么也没有等待,这当然很重要。那是几百万的损失您可以将其派发为股息(或支付更高的工资),而不是损失它们。
当然,大多数员工都处于薪资水平的低端,但即使是低端时间也属于金钱


3

我能理解几十年前为什么如此重要。计算机的速度要慢得多,内存也要少得多,因此您必须仔细考虑这些事情。

您似乎低估了N ^ 2增长的速度。假设我们有一台计算机,并且当N = 10时,我们的N ^ 2算法需要10秒。随着时间的流逝,我们现在有了一个比原始处理器快6倍的新处理器,因此我们的10秒计算现在不到2秒。在最初的10秒钟运行时间内,N仍然可以容纳多少个?现在,我们可以处理24个项目,是原来的两倍多。我们的系统要处理10倍数量的商品,速度必须快多少?好吧,它必须快100倍。对于N ^ 2算法,数据的增长非常快,并且比消除计算机硬件的进步还多。


另一个例子:如果处理一个元素需要30个CPU周期或10ns(这是非常便宜的),那么如果您只有10000个元素,该算法将已经花费了整整一秒钟的时间。在许多情况下,10000个元素并不多。
CodesInChaos

1

您不会相信我们在工作中使用的第三方业务程序的数量,而且与我的个人标准相比,其中许多使用起来非常荒谬。如果这些程序是我在家里使用的,那么很久以前我会用另一种程序代替它们。

在某些情况下,差异直接体现在成本上,因为某些程序直接影响我一天可以完成多少任务,从而降低了我的生产力和可计费项目的数量。因此,我想说,对于业务程序来说,至少要具有足够的性能以免成为收入的限制项目也很重要。

一个示例是事件管理,其中每隔15分钟测量一次工作(服务台)。如果程序运行缓慢,足以使一张票花费15分钟以上的时间(包括实际工作),它将大大减慢该过程。原因之一可能是数据库访问缓慢,只要用户执行某项操作(填写解决方案详细信息,更新工作信息或类似操作),数据库访问就会“等待一段时间”。我可以想象有些情况下,缓慢的程序甚至会影响到更关键的事情,例如住院患者关于紧急中毒事件的详细信息-可能是药物过敏或类似情况?


1

其他许多答案都相当详尽地涵盖了该主题,因此我将其原因和理由归于它们。相反,我想举一个真实的例子来说明算法选择如何产生实际影响。

http://windowsitpro.com/windows-xp/svchost-and-windows-update-windows-xp-still-problem

链接的文章描述了计算Windows XP更新的算法中的错误。在Windows XP的整个生命周期中,更新算法都可以正常工作。该算法计算补丁是否已被较新的补丁取代,因此不需要安装。到最后,被取代的更新列表非常长*。

更新算法是指数的,每次新更新花费的时间是前一次()的两倍。当列表进入40个更新范围(* long)时,以最大容量运行长达15分钟以检查更新。在更新过程中,这有效地锁定了许多XP计算机。更糟糕的是,当人们要安装更新时,该算法将再次运行,又需要15分钟。由于许多计算机都设置了“自动更新”,因此每次启动时可以将计算机锁定15分钟,并且有可能以一定的周期再次锁定。O(n) = 2n

Microsoft使用了短期破解(从更新列表中删除项目)和长期修复程序来解决此问题。这很重要,因为最新版本的Windows也使用相同的算法,并且有一天可能会遇到相同的问题。

在这里,我们可以看到算法的选择具有实际意义。错误的算法虽然可以在产品的大部分生命中发挥作用,但仍然会在未来产生负面影响。


0

我认为您是在解释有关性能的大量问题,这表明业务应用程序的性能要求很重要,而不是意识到提高性能很困难。使其发挥作用可以通过蛮力技术,反复试验或复制和粘贴示例代码来完成。

任何人都可以幸运并不断进行更改,直到运行速度更快,但这很少起作用。由于缺乏经验,开发人员将获得外部帮助。在某些环境中,性能改进是一个独特的问题,因此在诸如StackOverflow之类的网站上提出特定问题可能是唯一的选择。同样,许多顾问通过介入和解决这类问题来赚钱。


-1

这在很大程度上取决于您如何定义“良好性能”。您的算法应始终使用尽可能最佳的复杂性。滥用漏洞可加快您的平均网箱速度。在交互式程序中尽可能进行缓冲和预加载/预编译。

“良好性能”还有另一个定义:优化复杂性类的常量。这就是C ++的头衔,人们开始慢慢调用Java,这似乎是减少运行时间的5%。使用这个定义是正确的。随着时间的流逝,计算机硬件变得越来越复杂,而编译器变得越来越好。在某些时候,您无法真正真正地比编译器更好地优化低端代码-因此,顺其自然,专注于算法。

那时,使用Java / Haskell / C ++成为另一个设计决策。可以通过GPU上的OpenCL进行数字运算。用户界面需要固定时间算法,而且效果很好。输出和模块性比对齐类更重要,以使缓存利用率提高20%。多线程变得非常重要,因为人们不想要快速的应用程序,而是想要快速响应的应用程序。不重要的是,您的应用程序的运行速度始终比可能慢10%。甚至50%都可以(但是人们开始问问题)。专注于正确性,响应性和模块化。

我喜欢用Haskell或至少以函数形式(甚至是C ++)编程。能够轻松地为您的整个程序编写测试,比批处理作业快一点更重要。


-1

非常简单:成本

我以前的雇主有一个学习管理系统,该系统作为SaaS模型托管在物理服务器上。对于较旧的机器,JVM的堆配置为2 GB,对于较新的机器,JVM的堆配置为3 GB,我们为每台机器运行了多个实例。您会认为就足够了。

在我开始之前,有一个绩效团队负责使系统响应和扩展。他们发现,我们不断从数据库中查询某些数据。我们甚至已经将一张表加入大多数查询来检索一列。该数据很少更改。

麻烦的是,我们只有2 GB的空间可以使用。因此,显而易见的解决方案是开始缓存所有经常读取的数据。然后我们遇到了内存问题,就在我上任之前就开始了。

关于这一点,有两种思想流派:

  1. 如今,内存和硬件通常很便宜。只需购买更多的RAM,以便您可以缓存更多。
  2. 为什么学习管理系统需要3 GB以上的RAM?它所做的一切都会发出SQL查询,发送重定向以启动课程,并评估学生在课程中的进度。

第二个争论胜出,我花了一年多的时间调整内存使用率。

我目前的雇主还托管一个学习管理系统,但托管系统有所不同。可伸缩性非常差,以至于单个安装(分布在4个负载平衡的虚拟服务器上)只能处理80个客户。我们的一些大客户甚至拥有自己的服务器。导致此问题的大多数问题都是性能问题,例如占用所有CPU周期的SQL查询,内存泄漏,多次执行相同操作的冗余代码。我们甚至构建了一个内部应用程序,其唯一目的是在服务器性能不佳时重新启动服务器。有一个员工维护该工具(以及其他职责)。

他们订阅了我上面提到的第一个思想流派:投掷更多的硬件,因为硬件成本比开发人员的薪水便宜。

这没有达到预期的经济效果。在硬件,软件许可和支持人员来处理服务器之间,我们每年花费数百万美元以避免开发人员花费时间来分析代码。

加入后,我有责任解决可用性问题。由于我们大多数可用性问题是由于性能不佳所致,因此我一直在对代码进行性能调整,并且可伸缩性得到了显着改善,并且正常运行时间更长。我们准备开始增加密度。不用说,我的薪水还不到一百万(我希望!),所以花钱让我调整代码性能将最终为我们每年节省数百万美元。

TL; DR

如果您进行了全面的成本/收益分析,您将发现仅修复代码会更便宜。您忽略的一个已知性能问题会变成技术债务


1
并非每次成本/收益分析都会导致“修复代码”。程序员非常昂贵,如果您可以以低于程序员的成本增加RAM并仍能解决问题的话
罗伯特·哈维

很好的是,随着如此多的工作进入云托管情况,您可以看到您实际上为电力支付了多少费用。例如,我们将Amazon RDS用于数据库。最大实例与第二大实例之间的差异约为。每年$ 3500。您可以查看该数字,并判断是否值得花费大量程序员时间进行优化。
Carson63000

@RobertHarvey诚然,我不应该完全做到这一点。我的意思是绝对的“硬件比开发时间便宜”不是绝对正确的,但是您说得对,有时可能是正确的。
布兰登2014年

-2

我这样理解您的问题:为了获得足够好的性能(即用户感到满意,而我的后端不畏惧),我是否需要了解算法复杂性的理论?

它取决于您所说的“典型”业务应用程序的含义。在许多情况下,尤其是简单的类似于CRUD的信息系统,答案是否定的。对于这些,您将“仅”(有时实际上很难)需要能够跟踪性能瓶颈:我是否错过了数据库中的索引?我是否通过网络发送过多数据?我的angular.js前端有一千个手表吗?这是关于构建合理的体系结构,充分了解您的技术堆栈并避免废话。如果您是一位精通手艺的人,而不一定是计算机科学家,则可以实现。换句话说,构建Oracle查询优化器的人员处理了算法复杂性问题,您只需要正确使用他们提供给您的内容即可。

现在有例外。如果我们在谈论大数据或机器学习,那么您需要知道自己在做什么,而不仅仅是使用可用的默认算法。即使在前端,如果您开始构建高级数据可视化,其中的一些可视化也可能意味着非线性复杂性成本(例如,力布局图)。

如今,这些例外情况变得越来越普遍,而且当您寻找可以处理这些问题的人时,市场也非常干燥。所以:是的,没有计算机科学背景的人就可以成功,但是如果有一些背景,您将获得更多。


-2

其他响应者涵盖了大多数基本点,但是对于可以并行执行的任务,低效的软件会导致更多服务器的形式增加硬件成本,这些服务器使用更多的电源,并且需要更多的空间和维护。

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.