递归代码在UNix框上运行缓慢但在Windows上运行速度很快

时间:2015-11-27 08:49:13

标签: java unix recursion

我有一个java代码,它是while循环和递归的组合。我们面临的问题是,对于unix盒[HP ProLiant BL460c G7]而言,调用以下方法需要的时间几乎是Windows盒[Intel Xeon CPU E5-1650,64位Windows 7]的8倍。关于如何在Unix框中改进执行时间的任何想法。 我们使用的是JDK 1.6_43 [64位]

protected Date abc(int n, Date date) 
{
    long tStart = System.currentTimeMillis();

    if (n > 0) 
    {
          while (n > 0)
          {
                --n;
                date = getNextExchangeDateUnadjusted(date);
          }

          return date;
    }
    else 
    {

          Date nextExchangeDate = getNextExchangeDateUnadjusted(date);

          Date previousExchangeDate = getNextExchangeDateUnadjusted(date);

          while (!abc( -n + 1, previousExchangeDate).equals(nextExchangeDate)) 
          {

                date = date.addDays( -14);

                previousExchangeDate = getNextExchangeDateUnadjusted(date);

          }

          return previousExchangeDate;
    }
}

编辑:

以下是上面提到的getNextExchangeDateUnadjusted方法的代码

public Date getNextExchangeDateUnadjusted(Date date) {
    // Third Wednesday of each month
    Date thirdWednesdayInMonth = date.getThirdWednesdayInMonth();
    if (thirdWednesdayInMonth.after(date)) {     
      return thirdWednesdayInMonth;
    }
    return date.addMonths(1).getThirdWednesdayInMonth();
  }
}

还要添加该代码在此部分中花费最长时间:

      while (!abc( -n + 1, previousExchangeDate).equals(nextExchangeDate)) 
      {

            date = date.addDays( -14);

            previousExchangeDate = getNextExchangeDateUnadjusted(date);

      }

EDIT2:

随着进程的推进,我们在Unix机器上进行了多次堆转储,发现“保留堆”从大约1mb开始增长到450mb,因此堆栈大小正在大幅增长。不确定这是否会导致性能下降。我们现在将在Windows中进行堆转储,并且还将尝试使用XSS更改堆栈大小。

2 个答案:

答案 0 :(得分:1)

采用多管齐下的方法来解决这个问题:

  1. 我们排除了任何IO或远程呼叫导致不必要的延迟。
  2. 通过Visual VM获取堆转储,以查看流程中的任何异常行为,并在Unix和Windows之间进行比较。我们在这里可以追溯的是主线程占用了4.5mb的堆栈空间,但在Unix和Windows中都是一样的。
  3. 现在只剩下选项是查看JVM在unix和windows上是否存在任何差距,以及2之间是否存在任何优化差距。
  4. 问题在3部分中被发现,以下是我们运行命令java -version

    时的差距
    • 在Windows上

      java版本" 1.6.0_43"

      Java(TM)SE运行时环境(版本1.6.0_43-b01)

      Java HotSpot(TM)64位服务器VM(版本20.14-b01,混合模式)

    • 在Unix上

      java版本" 1.6.0_43"

      Java(TM)SE运行时环境(版本1.6.0_43-b01)

      Java HotSpot(TM)64位服务器VM(版本20.14-b01,解释模式)

    您可以在unix和windows之间看到JVM热点模式的明显差异。在进一步调查中,我们发现在Interpreted中运行的JVM并没有优化代码[本文详细介绍了它:https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-1-jvm-types-and-compiler-modes/]。 所以我们在Unix框上启动了我的进程,标志为-Xmixed,迫使JVM在混合模式下工作。这解决了我们的问题,Unix和Windows性能变得相同。

    编辑:

    由于unix框中的此参数,JVM被推送到解释模式:-Djava.compiler=NONE

答案 1 :(得分:-1)

我建议您先用笔和纸来修复代码中的逻辑。

我跟你做了

assume abc is initially called as abc(1, "date < 3th Wednesday")
it will return "3th Wednesday in the same month"

assume abc is initially called as abc(0, "date < 3th Wednesday")
1. while loop iteration
abc(1, 3th Wednesday in the same month)
  - return 3th Wednesday of month+1
- as this is not equal with the "3th Wednesday in the same month"
   (nextExchangeDate) you compute "date - 14 day"
2. while loop iteration abc will be called as abc(1, "date - 14 day")
which return "3th Wednesday of month-1"
3. while loop iteration abc will be called as abc(1, "3th Wednesday of month-1")
...

我停了下来。它看起来更像试验和错误然后计算。在寻找性能差异之前,我会先解决这个问题。

这里有一个计算的例子

开始日期&#34; 16.11.2015&#34;并且n = 1

abc(1, 16.11.2015)
16.11.2015 get 3th Wed ==> 18.11.2015
abc date: 18.11.2015

开始日期&#34; 16.11.2015&#34;并且n = 0

abc(0, 16.11.2015)
16.11.2015 get 3th Wed ==> 18.11.2015
16.11.2015 get 3th Wed ==> 18.11.2015
abc(1, 18.11.2015)
18.11.2015 get 3th Wed ==> 18.11.2015
18.11.2015 + (1) month
18.12.2015 get 3th Wed ==> 16.12.2015
16.11.2015 + (-14) days
02.11.2015 get 3th Wed ==> 18.11.2015
abc(1, 18.11.2015)
18.11.2015 get 3th Wed ==> 18.11.2015
18.11.2015 + (1) month
18.12.2015 get 3th Wed ==> 16.12.2015
02.11.2015 + (-14) days
19.10.2015 get 3th Wed ==> 21.10.2015
abc(1, 21.10.2015)
21.10.2015 get 3th Wed ==> 21.10.2015
21.10.2015 + (1) month
21.11.2015 get 3th Wed ==> 18.11.2015
abc date: 21.10.2015 (the 3th Wed of previous month)

我不相信没有更好的计算方法。