内存 vs. 性能

18

在编程时,这一直是我心中的疑问,所以我想在它真正影响我之前说出来。

我应该更担心什么?应用程序使用的内存还是它所需的性能。我的意思是,我应该专注于减少应用程序的内存使用量,并使用更多的性能(例如通过数据库加载并在使用后丢弃),还是减少性能使用并使用更多内存(例如缓存)。

我的应用程序条件: - 这是一个服务器应用程序,不适合在桌面等其他设备上运行,我有6GB的RAM和四核处理器。


内存访问也很昂贵。 - Gumbo
16个回答

21

你的问题已经得到了很多类似于禅宗佛教的回答,我希望能做得更好。

内存限制是硬性的:如果超出限制,即使有虚拟内存,你的应用程序也会变得缓慢不堪,成为大家嘲笑的对象。

CPU时间是没有限制的:你的应用程序将花费需要的所有时间;希望它足够并行,以至于所有4个CPU在大部分时间内都可以发挥最大效率,直到你的应用程序完成。

许多计算机科学问题有多种解决方案,其中包含不同的内存与时间之间的权衡。因此:在使用至少一半内存之前,要慷慨地使用内存(如果这有所帮助;不要浪费内存!),但是要停下来留出足够的内存,以免在特殊情况或意外情况下超出限制。

现在,你已经分配了内存资源,可以尝试通过代码微调获得更小的性能提升。但不要过度纠结。

完成了。

P.S. 如果它不能正确可靠地工作,那么前面的所有努力都是徒劳的。时刻记住这一点!

祝你好运。


4
理论上,CPU 时间与硬内存限制的公式是正确的,但在实践中,你可以很容易地增加内存(添加或替换 RAM 芯片),但 CPU 的运算能力受到限制,提高它的成本要高得多! - Frunsi
1
我理解你的观点,你是对的(在慷慨使用内存的情况下)。但在当前实践中,决策往往是浪费内存,特别是在服务器应用程序中。因为内存便宜且易于扩展! - Frunsi
2
我们大多数时候意见一致。但我想指出,在企业环境中,升级内存的实际成本可能与实际采购成本相差很大。我曾经遇到过这种情况:为现有机器增加内存比购买新机器更简单,[叹气]。我也同意许多开发工作由于缺乏更好的知识而浪费资源。 - Carl Smotricz
2
我完全同意。说得好。 - Kyle Johnson

6
这取决于程序的类型。如果您可以控制目标机器,那么就会更容易一些。如果您知道即使在极端情况下,您也不会用完内存,那么您可能会尽可能地使用所有可用内存。没有任何优势可以利用未被任何内容使用的内存。
总的来说,我认为事物可以分为几类。
补充程序:如果该程序不执行机器的主要用途,则应尝试节省内存。虽然不是服务器问题,但我通常在这种情况下考虑的例子是桌面小部件和Tomboy。它们不是主要用途,因此不应从系统中夺取太多资源,这可能会影响主要应用程序的性能。
常规应用程序:这些具有简单的优先级。首先完成所需的工作,然后如果速度慢,请加快速度。除非您很鲁莽(或使用Python或Java:-),否则不需要太担心内存。
许多实例应用程序。如果您希望用户拥有许多应用程序实例,例如多个任务或仅在同一任务中的多个实例(例如多个Firefox窗口/选项卡),因为事物会成倍增加,您需要掌握内存使用情况。速度并不是使操作更快的问题,而是确保空闲实例实际上没有进行任何处理。
巨型应用程序:如果您的应用程序实际上有一个巨大的任务,例如图像处理,则应从一开始考虑内存使用情况。我怀疑Evolution消耗了很多内存(目前在我的机器上为142兆字节),因为它们有一个巨大的任务,但没有意识到这一点。我有很多电子邮件,大多数来自列表,
如果您可以控制目标环境,那么您只需要拥有所需的内存,这对您来说更容易。如果其他用户将使用您的程序,则需要更多的内存仍然对您来说更容易,但对用户来说不太友好。
我正在OLPC XO上开发,主要是尝试使系统与补充程序配合得很好。这意味着我非常注重低内存使用率,但即使在受到内存限制的系统上,我发现进一步减少内存使用率也没有太多用处。启动后,它有超过150兆字节的可用内存。这足以运行您想要的所有轻型应用程序,但大多数较重的应用程序会很吃力。中间地带几乎没有。如果优化2兆应用程序以仅使用1兆,那么如果您运行Firefox之类的应用程序,则不会有太多余地。

只是一点提醒:现在算法和库的选择比编程语言更重要。是的,Java和Python使用的内存比C多,但当你加入各种级别的DBMS、缓存等因素时,算法和方法的选择就变得更加重要了。 - BobMcGee
我完全同意关于库的观点,我正在考虑写另一个回复来讨论这个话题。尽管有人说“先让它工作,然后再进行分析和优化”,但如果你严重依赖库,那么这种方法就没有用了。如果你先让它工作,然后进行分析,发现由于程序所依赖的库而导致系统过慢/庞大,通常唯一的解决办法就是重写。如果库具有明确定义的行为边界和良好的接口,则不必如此,但太多的库想要控制你的程序结构(如GTK等)。 - Lerc

5
考虑您要处理的数据量和所需的响应速度。认真考虑设计方案,建立可维护的系统并使其运转起来。然后进行性能分析,并解决实际的瓶颈问题。

2
这个答案相当不完整,没有什么帮助性 -- 我认为它需要一些响应性的例子。生成一个网页需要多长时间才能让用户看到?发送一封电子邮件?在CMS中索引内容?答案是不同的,而且比“你需要的响应性”更加复杂。 - BobMcGee
@BobMcGee 这个回答和问题一样具体和完整。问题没有告诉我们是否涉及网页、是否涉及 CMS,是否有电子邮件问题。这个问题需要一个通用的答案,建议退后一步,思考对提问者来说应该重要的事情。一旦他知道了这些,并有一个适当的设计来解决这些问题,那么可维护性和正确性就比性能更重要。 - retracile

5

这个问题与编程本身一样古老。不幸的是,答案是“要看情况”。如果您正在为一个有32GB内存的系统编写应用程序,并且您的软件是唯一运行的内容,那么您应该编写代码以利用它。另一方面,如果您正在编写将在嵌入式系统上运行的代码,那么您可能应该尽可能地使用较少的内存。最重要的是,您要意识到这些权衡,对您的代码进行分析,并优化最大的瓶颈。


4
  1. 让它工作。

针对不同的应用程序,你会得到不同的答案,实际上这取决于具体情况。除了以下一句话,没有一个通用的答案涵盖所有情况:

  1. 让它工作。

有时候软件可以过度思考。

具体来说,大多数操作系统在缓存磁盘 I/O 方面表现出色。举个例子,如果你正在处理大量 SQLite 数据库连接,那么在你建立几个连接后,操作系统很可能已经将整个内容缓存在内存中。在大多数情况下,不要过度思考操作系统。


3

没有一种正确的选择-这取决于您的应用程序及其要求。但是,通常只能选择一种-您通常无法同时最大化性能和减少内存消耗(如果有的话)。如果这是任何关键系统,客户应指定内存的最大限制和/或性能的最低限制-如果他们没有这样做,他们应该这样做。


3

我目前在处理与我的当前项目相同的困境。有三个方面:可读性速度内存。在我拥有的替代解决方案和库中,每个方面都很好。我的结论是(按降序排序):

  • 可读性(良好的语法和逻辑)
  • 内存(将事物的内存限制为RAM的1%)
  • 速度(越多越好)

主要目的是编写未来的代码。代码有生存、生活和繁荣的渴望。没有什么比良好、简单的代码更好:美丽的语法、易于遵循的逻辑和直观的步骤。选择最可读的代码。

服务和应用程序按顺序共享CPU:一个接一个地运行,并经常等待许多微秒。它们并行共享RAM:所有人都占用一定的内存。

实现一个解决方案,确保在实际情况下内存永远不会超过限制。请记住,操作系统和其他应用程序与您共享内存。 RAM的几个百分点对于您的应用程序来说应该足够了。 然后,您可以考虑解决速度瓶颈(太多循环或等待时间过长)。


2

它们两个都很重要。你可能想要将某些对象缓存到内存中以获得更好的性能,这可能会增加内存占用。另一方面,如果你的应用程序花费大量时间进行垃圾回收(如在 .net 中),或者有未释放内存的非托管资源,那么你将遇到性能问题。


2

最好不要抽象地思考,而是从具体的设计角度出发。

  1. 如果你的RAM用尽了,你会后悔的,所以尽可能保持数据结构的简洁和简单,即使看起来你可能需要编写一些看起来效率低下的循环。因为担心性能而复杂化代码和数据结构是过早优化的本质。尽管人们反对过早优化并声称他们不这样做,但他们仍然会以可怕的程度这样做。

  2. 当它正在工作并且做你需要它做的事情时,如果你实际上有一个或多个性能问题,那么处理性能。通常的方法是使用分析工具,但这是我喜欢的方法

小心多核。并行和线程允许您在时间上重叠地获取多个代理,例如磁盘头、CPU或人类客户端。例如,如果您的进程是I/O限制的,则尝试在多个核上执行它们不会有太大帮助,反而可能会损害性能。如果只有一个物理磁盘驱动器,则尝试重叠I/O限制的线程可能不会带来太大的收益,并且可能会损害性能。另一方面,如果您对每个用户有一个线程,那可能是有意义的,因为这些线程大部分时间都在等待用户。


我同意IO绑定的观点。特别是考虑到新的英特尔架构似乎要快得多,而磁盘速度并没有相应增加。这为使用更多内存提供了充分的理由 - 您更有可能受到磁盘限制,并且将更多内容放入内存中将使CPU保持工作状态。 - AngerClown

1

即使您提供了规格,这仍然取决于应用程序将要处理的工作负载。

  • 如果您一次处理少量数据,则可以通过预取下一个N个块来优化性能,从而增加内存消耗。
  • 如果您的数据相当大,则很快就会完全填满主内存,并且向前读取将导致抖动(例如,向前读取会强制在完全处理之前将数据写回磁盘/数据库;然后您需要将此数据返回到内存中,从而强制交换这些预读值)。

因此,首先获得您的应用程序的工作版本。然后进行分析,查看瓶颈在哪里。(过早地进行优化是万恶之源!--唐纳德·E·科诺斯)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接