质数性能差异 ACF vs. Lucee

13

以下代码用于查找质数,但Adobe ColdFusion(10)和Lucee(4.5)在性能方面存在很大差异。 在相同的机器上进行测试(6C i7 3930k @ 4 GHz,Windows 10 64位,两个CFML引擎的JVM内存设置相等:JDK7 -Xms512m -Xmx2048m -XX:MaxPermSize=512m):

<cfscript>
    ticks = getTickCount();
    stopIndex   = 10000;
    primes      = [];
    divisions   = 0;
    primes.add(2);
    primes.add(3);
    n = 5;
    for (n; n < stopIndex; n += 2) {
        isPrime = true;
        d = 3;
        for (d; d < n; d++) {
            divisions++;
            if (n % d == 0) {
                isPrime = false;
                break;
            }
        }
        if (isPrime) {
            primes.add(n);
        }
    }
    ticks = (getTickCount() - ticks);
</cfscript>

<cfoutput>
    <p>
        #numberFormat(divisions)# divisions in #ticks# ms.
    </p>
    <p>
        #numberFormat(arrayLen(primes))# prime numbers found below #numberFormat(stopIndex)#.
    </p>
</cfoutput>

stopIndex @ 10k

  • ACF: 280毫秒
  • LUC: 1300毫秒

stopIndex @ 20k

  • ACF: 1000毫秒
  • LUC: 4800毫秒

stopIndex @ 30k

  • ACF: 2200毫秒
  • LUC: 10500毫秒

trycf.comcflive.net 显示了类似的差距。

我检查了 cfscript(与标签相比)对时间有影响吗?没有。CFML 引擎相关的服务器设置似乎也没有任何明显的影响。

性能差异的原因可能是什么?
我如何可能解决这个问题?

背景:我在生产服务器上运行重型数学操作(几何、图像渲染),该服务器恰好运行 Lucee,并注意到性能低下。


2
在执行过程中获取堆栈跟踪并查看哪些代码运行最多。此外,对虚拟机上的内存使用情况进行分析以查看是否有差异。 - Brad Wood
3
@alex 谢谢你提出这个问题。我已经和 Lucee 团队讨论过了,我们将深入研究一下为什么 ACF 和 Lucee 之间存在性能差异,并看看在 Lucee 中是否有任何性能提升的空间来改善这种情况。 - andrewdixon
3个回答

2

整数运算比浮点数运算慢,因为Lucee将变量存储为类型的方式而导致此代码运行较慢。如果你强制将n设置为非整数,则Lucee的运行速度会快4倍。

if ((n+1.0) % d == 0) {

这个调整还将ACF的速度提高了一倍以上。 https://luceeserver.atlassian.net/browse/LDEV-1541

0

我认为性能问题方面应该由Lucee来解决,而不是你和你的代码。

然而,从整体性能的角度来看,最好的经济效益是循环到sqr(n)+1而不是一直到n。你做了比你需要做的更多的工作,这比平台差异对代码性能的影响更大。

此外,你只需要循环前面的质数,而不是每个(第二个)数字。这将进一步提高你的性能。

我知道算法只是一个例子,但老实说,其余部分不是你可能能够修复的。提交一个Lucee票据并等待它被修复(或者如果你有时间/Java知识,可以自己动手修复)。


0

我知道这不是回答问题的方法,但是进一步考虑Adam的评论,它甚至不必达到平方根。一旦你意识到一个数字不能被3整除,你就可以将顶部限制在3的除法结果上。当n变大时,跟踪以前的质数需要内存。如果你能承受得起,那太好了。如果你不能,那么将分母增加2会加速2倍,因为你跳过了偶数。这段代码快了约50倍:

<cfscript>
    ticks = getTickCount();
    stopIndex   = 10000;
    primes      = [];
    divisions   = 0;
    primes.add(2);
    primes.add(3);
    n = 5;
    for (n; n < stopIndex; n += 2) {
        isPrime = true;
        d=3;
        n2=n;
        for (d; d < n2; ) {
            divisions++;
            Result=n/d;
            if (Result eq Int(Result)) {
                isPrime = false;
                break;
            } else {
              d+=2;
              n2=Result;
            }
        }
        if (isPrime) {
            primes.add(n);
        }
    }
    ticks = (getTickCount() - ticks);
</cfscript>

32毫秒内完成了56,570个分割(与我的计算机之前的1500个相比)

在10,000以下找到了1,229个质数。


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