您是否应该尽量减少创建许多小对象?


10

在编写经常创建许多(1000个)小对象的东西时,您是否应尝试将其最小化以提高性能?特别是如果您不知道它将在低端台式机到高端台式机甚至是移动设备上运行的系统。对于移动设备,我听说创建很多对象会严重影响性能,尽管我不知道那是多么真实。

我有一个例子很好地说明了这个想法。例如,在图形程序中,存在一种理想地用于所有绘图的方法drawPixel(Point)。可能会创建1000点,并且可能会经常重复,例如在游戏中每秒可能会被调用60次以上。或者,drawPixel(int x, int y)可用于最小化许多Point对象的创建。

在面向对象的设计中,我认为首选使用Point。但是,使用基本类型可以提高性能。在大多数情况下,性能提升可以忽略不计,但是我不确定移动设备或旧机器之类的东西。这样做会提高性能,应该考虑吗?


我很难找到支持它的参考,但是一般而言,在Java 8中,不必担心。不要做明显的愚蠢的事情,但是如果您不是故意浪费,那么系统应该可以正常工作。Sun / Oracle已经有大约20年的时间来调整GC和内存管理,并且他们真的很擅长。

@Snowman我听说过Java的新版本在内存管理方面做得更好,但是我看到的问题是不能保证用户没有使用旧版本。这就是引起我这种担忧的部分原因。
条纹

1
首先做一些性能测量。如果您有任何麻烦,请考虑如何进行优化。但是请不要过早牺牲代码的可维护性,因为您认为可能会遇到一些性能问题。
斑点

2
@Stripies在Java中已经回答过的短暂Java对象的性能我们应该避免在Java中创建对象吗?。但是,如果您每秒必须处理数亿个这样的对象,则仅在那时重新考虑此问题。
rwong

1
如果您担心Java的旧版本,请在安装时进行检查。一个足够老的JVM会引起内存管理问题,同时也存在许多众所周知的安全问题,因此提示用户进行更新对他们有帮助。System.getProperty("java.version")(或“ java.vm.version”)是一个起点。
杰里·科芬

Answers:


17

通常,,您不应该避免创建对象,以免造成性能损失。有几个原因。

  1. 使用对象是使用Java的重点。预先避免使用它们是一个标志,表明使用Java的决定可能不是正确的选择。
  2. 众所周知,性能问题很难预测。永远不要以为是瓶颈。总是测量。性能工程几乎总是在正确的位置进行小的更改的问题。如果没有测量,就无法预测正确的位置,而没有实验就无法预测药物的效果。
  3. 创建对象的成本被大大高估了。在现代JVM中,它基本上等于增加一个指针(对于分代垃圾回收器来说,管理它的成本也是微不足道的)。互联网上有很多文本建议您避免使用对象,使用对象池等。今天,它已经过时了。您不太可能获得足够的性能来证明避免使用Objects或自己管理Objects所带来的增加的开发成本和复杂性。

就是说,有些地方一开始就没有意义。将两个坐标传递到绘图例程可能是这种情况:坐标对没有独立的存在,没有标识,仅使用一次然后立即丢弃等。

如果是这种情况,那么可以肯定,继续并传递两个ints而不是将它们包装到一个对象中。OOP的要点不是所有内容都必须是一个对象。关键是,在自然解决数据表示问题的地方,对象使开发变得容易。不要在有意义的地方避开物品-不要在没有意义的地方介绍他们。


2

在编写代码之前考虑对性能的影响时,应该假定您不知道自己在做什么。

Java和原语相比,对象的空间开销非常小。您的对象越小,开销的百分比就越大。但是,我很久以前就知道,与将n乘以n的东西相比,将n乘以2的东西什么都没有。

因此,虽然可以,但您可能会拖延某些影响尺寸一半甚至四分之一的系统,请问自己为什么真正在意。解决该问题的复杂解决方案将不会受到欢迎。特别是因为深入研究此类代码会造成混乱。困惑的程序员编写错误的代码。他们编写了n次n次代码,应该是n次n次代码。他们花了更长的时间去做。

现在,如果您可以通过一些适合我的盒子的技巧来节省我的空间,则我不必在大多数时间都在里面聊天。如果是一个盒子,当那个盒子更好用时,我可以换掉另一个盒子,我什至可以付钱。


2

在我完成的性能调整(示例)中,内存管理非常容易成为罪魁祸首。我不在乎他们对操作符和垃圾收集器进行了多么疯狂的调整,最快的计算就是没有计算。因此,如果我发现内存管理器花费了很大一部分时间,并且无法避免制造对象,那么我会找到一种方法来重用它们,而不是不断地制造新对象。

仅在必须制造对象时才这样做。对于图形,通常我不知道。恕我直言,应该绘制图形,而不是构建图形。当然,您可以说图片由点,连接它们的线,多边形,文本等组成。这并不意味着您没有其他选择可以在绘制对象之前用它们制成对象。我只是画出来。

有一个Paint方法。我将其覆盖,将所有内容绘制到位图,然后将其阻止传输到屏幕。它看起来是瞬间的。对于鼠标输入,有一些方法可以覆盖,检测单击,拖动等等。

出于某些原因,OOP是一个好主意。这些原因并不适用于所有情况。


我同意,但我也同意其他所有人的观点,即确定无疑是唯一的方法。在优化之前,请确保您有使用规范的简单/明显方法。但是我同意,新规范仍然是一个问题。
比尔K

2

继续使用少量分配。现代内存管理器,尤其是高度优化的Java对象管理器,非常高效。为工作程序保存主要的性能优化。

整体性能非常有可能满足要求。如果您发现情况并非如此,则(仅)然后,分析代码的性能。在漫长的软件开发生涯中,我了解到瓶颈几乎是您所无法企及的。

我曾经让一个团队成员花几天的时间使对象成员查找速度提高20倍。成功!但是,实际使用中最佳的整体加速比以百分之一的百分数衡量。更改被立即撤消,因为加速要求每个成员的内存分配更大。


1

很简单:如果您需要1000个小对象,那么您就可以创建1000个小对象,不必担心。如果您需要 100个小对象,那么创建1000个小对象是愚蠢的-创建所需的对象而不是更多。

如果您担心性能(如果您也不担心性能),则应该一次将任何功能编写一次,这会使您的整个代码更容易理解。然后,如果您遇到性能问题,那么进行测量可能会告诉您,性能问题发生在一个地方,这使事情变得容易,而您只需要更改一个地方。或测量表明,这个地方不会造成任何问题,所以您就完成了。

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.