参数对象与长参数列表

时间:2015-06-17 22:46:00

标签: java performance memory jvm stack

我理解在使用长参数列表处理方法时使用参数对象的原因。但我有一种情况,我想减少代码的内存占用。

  

我的问题是从绩效的角度来看。多少   我可以通过访问一个长参数列表获得好处吗?

用例是这些方法最终会被调用数千次,每次调用时,都会创建一个新的参数对象。我想真的避免创建所有这些参数对象。

有没有"我可以吃蛋糕,也可以吃它#34;封装参数的解决方案,只使用堆栈存储?

不幸的是,调用链中有多种方法需要所有这些参数,我不介意进行此更改,因为这些方法不公开。只是想知道更好的解决方案。

进行此更改会影响大部分代码,并且会耗费大量时间。只是想在我采取这条路线之前检查这是否值得做出改变。

数据结构

数据结构是一个对象图。对象是业务数据,连接它们的边是调用。这些边与参数数据相关联。使用参数对象很漂亮,我的代码运行得很好。但我对性能并不满意,并希望改进它。

我已经分析了我的代码,这些对象是内存开销的一个重要部分。我怀疑他们是否对CPU开销有很大贡献,但我绝对关心内存。

  

此数据结构将成为将在a中使用的框架的一部分   高度并发的环境。因此,减少内存占用是我最关心的问题。

参数对象有大约10个字段和一些与之关联的行为。我总是可以替代地封装行为。

4 个答案:

答案 0 :(得分:1)

有很多技巧。

如果您担心内存开销,可以创建一个固定的参数对象池,然后在将它们释放到池中时清除它们。这样你从池中获取一个参数对象,设置值(我希望是原始值),然后传递它。完成后,您将参数对象放弃到池中,然后允许重用它。

请记住,Java中的对象创建与C ++或其他语言中的对象创建具有相同的性能(对象通常在创建时非常昂贵)。在某些情况下,如果有任何东西,额外的对象不会花费太多,因为JVM优化单个对象创建通常会占用支持六个或更多“新”调用所需的内存。

最后,关于使用堆栈存储,Java中支持对象的“堆栈存储”,但为了使其与语言设计保持一致,它在JVM的遗产中完成,并且在代码中具有相同的表示作为堆存储对象。我并不完全熟悉人们用它来准备可能的堆栈存储的技术,但我知道你无法保证它。

答案 1 :(得分:1)

经过进一步调查后,我发现了这一点。

使用长参数列表替换参数对象不会提高性能,除非以下内容为真

  

参数对象的保存期限不超过内存

我从这个练习中学到的东西有助于阐明参数对象的对象生命周期

它有助于确保参数对象确实是短暂的,并且不会在代码的其他部分中不必要地共享。我不得不做一些重构以确保这一点,我最终保留了参数对象。

答案 2 :(得分:0)

取决于你的情况。对象创建的主要问题(在缺乏资源的环境中)是内存消耗和对象创建时间。

在大多数情况下,如果您没有多个嵌套对象,则对象创建时间会很快。对于内存开销,计算基元的数量并将它们乘以各自的内存开销,然后为对象本身添加八个字节。 (当然,对任何包含的对象都是递归的。)

对于字符串的情况,它大致(40 + 2 *字符数)字节。这显然是可以改变的,但不是很显着。对于基本数组,将原始成本乘以容量,然后再加上16。

创建的O符号基本上是构造函数的O符号。我确定有一点开销,但没什么大不了的。对于一个简单的参数对象,它可能是无关紧要的。

不要挤满您的日程安排,但如果效率非常重要并且答案不明显,那么最好的方法就是对这两种方法进行基准测试。

正如我所说,我不知道你的具体情况。但是,我过去通过工厂模式的智能偏差解决了类似的问题。但是,这需要另一个课程,听起来这对你来说是一个问题。

答案 3 :(得分:0)

  

我的问题是从绩效的角度来看。多少   我可以通过访问一个长参数列表获得好处吗?

避免长参数列表有多种原因,所有这些都在Effective Java,2nd Ed中对Builder模式的处理中进行了阐述。

如果您的方法是仅由您使用和维护的内部类的一部分,那么使用许多参数可能没有任何害处。但是要记住一些事实。长参数列表:

  • 使您的代码更难阅读
  • 可能会增加难以调试错误的可能性,尤其是如果列表包含多个可能无意中转置的相同类型的参数
  • 导致您的程序难以维护
  • 如果将方法导出到无法频繁访问文档但无法使用该方法的客户端,则
  • 会导致您的API失效

事实是,优化(例如伸缩参数列表)的影响经常被夸大。是的,JVM将使用伸缩模式削减一些方法的执行周期...但是考虑到如果该方法占整个项目(常见)的总CPU处理的不到10%,那么优化就毫无价值。

  

"首先让你的程序正确,然后......然后......制作   它很快,但只有在分析表明你需要时才会这样。"

事实上,相对于使用捆绑对象上的构建器模式以及需要大量参数的方法的许多好处的优化可能会导致您浪费时间和金钱。

  

用例是这些方法最终会被称为数千个   每次调用时,都会有一个新的参数对象   创建。我想真的避免创建所有这些参数对象。

对于现代JVM,用于创建和垃圾收集短期轻量级对象的处理时间通常优于对象池。

您的担忧是有效的,但您确实需要执行性能分析以查看是否存在执行优化的内存或性能原因。如果优化成本可能会以其他方式降低成本(可维护性,可读性),则尤其如此。