【问题标题】:Optimization of long method chain in JavaJava中长方法链的优化
【发布时间】:2017-12-07 22:22:34
【问题描述】:

分析应用程序中一些预先存在的第三方Java 代码(无法重写),我发现它几乎完全是由长方法链构成的,形式为

public Object process() {
  // Do some class-specific stuff
  return this.getChild().process();
}

其中有一个定义process() 方法的基类,由重新定义该方法的子类继承,并且在最后重复getChild() 调用。

由于条件块,在运行时会创建(分支)多个此类链,其中一些可能会相对较早地返回(例如,在链中的 10-20 个“链接”之后),但最常见的是“长度”在返回结果之前,链的数量要大得多,甚至可以超过 100 次连续的方法调用。

应用程序使用此代码处理大文件,每次调用顶级方法时结果都会发生变化,通常每个文件的每个不同行都会发生一次。

那么,两个问题:

  • 与“常规”设计相比,这种设计对性能有何影响?
  • 是否有任何技巧可以显着提高该代码的性能(例如,通过更改某些 JVM 参数)?

【问题讨论】:

  • 为什么你认为这是一个性能问题?您是否有分析数据来支持您的担忧?什么是“常规”架构?完全不清楚你在这里问什么。
  • “常规”是指具有短方法链的架构。问题是关于评估任何性能影响。如果共识结果是“预计不会影响性能”,那就这样吧。
  • 没有“长方法链”和“短方法链”之分,无论哪种方式,您都可以获得深度调用堆栈。由于调用深度而担心性能可能是浪费时间,除非您已经对系统进行了概要分析并确定了瓶颈。

标签: java optimization methods chaining


【解决方案1】:

方法调用非常快(每秒 10 或 100 次),因此首先通过分析系统来确保它实际上是有益的。

否则,您可以使用缓存来提高效率,特别是如果您的结果是一致的(相同的输入,相同的输出)。

例如:

Object cache = null;

public Object process() {
   if (cache == null)
      cache = this.getChild().process();

   return cache;
}

如果涉及某种类型的输入或状态,那么您可以使用Map 作为缓存,它使用输入值的键并存储输出值的值。

【讨论】:

  • 是的,这是一个明显(也很聪明)的选项,但在这种情况下不适用,因为代码用于处理大文件,并且每行的结果都会发生变化。我在问题中澄清了这一点。谢谢,无论如何+1。 :-)
  • @PNS 需要更多详细信息。一定有可以缓存的东西。否则,方法调用非常快(每秒数百万次),因此您可能无需担心。
  • IMO“非常快”和每秒几百万或几百万是矛盾的。同时,像两个整数相加这样的普通事情每秒可以完成几十亿次,如果你有一个好的 CPU,超过 100 亿次。
  • @harold 是的,速度是相对的,但是当你可以在一毫秒内赚到 50 万时,没有理由担心 100 次方法调用
【解决方案2】:

形式的陈述

return getChild().process();

不一样
SomeType var = getChild();
return var.process();

在这两种情况下,都会依次调用一个方法,并且getChild() 的返回值将用作process() 调用的接收者。

如果您正在寻找不相关的次要技术细节,第一种形式不需要局部变量。但由于在 HotSpot 中,在创建线程时预先分配了固定大小的堆栈内存,因此无法感知这两种形式之间的任何性能差异。

这两种形式的选择纯粹是一种风格。

【讨论】:

  • 我认为他的担忧与它是一个 递归 调用有关,有时会达到 100 层,而不仅仅是它一个接一个地调用两个方法。跨度>
  • @Holger 除非一些 JVM 再次通过链接 google.com/url?sa=t&source=web&rct=j&url=https://… 做了一些有趣的事情:)
  • @DaveCousineau:这就是这个答案的重点,没有递归。这两个链式调用与具有中间赋值的两个调用没有什么不同。一旦你理解了这一点,你就会明白这也适用于一百个链式调用。它们仍然与一系列未链接的调用没有什么不同。用一百次调用写下来只会弄乱答案。
  • @Eugene:但这实际上与链接无关,而是与优化更常见的模式有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
相关资源
最近更新 更多