13

以下用于查找素数的代码在 Adob​​e 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>

停止索引@10k

  • ACF:2​​80 毫秒
  • LUC:1300 毫秒

停止索引 @ 20k

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

停止索引 @ 30k

  • ACF:2​​200 毫秒
  • LUC:10500 毫秒

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

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

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

背景:我正在生产服务器上运行繁重的数学运算(几何、图像渲染)),而该服务器恰好正在运行 Lucee,并注意到性能缓慢。

4

3 回答 3

2

整数数学比浮点数学慢,因此由于 Lucee 将变量存储为类型的方式,它的运行速度较慢。如果你强制 n 为非整数 Lucee 运行速度快 4 倍

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

这个调整也使 ACF 的速度提高了一倍以上

https://luceeserver.atlassian.net/browse/LDEV-1541

于 2017-10-09T01:04:42.580 回答
0

我知道这不是在回答问题,但进一步考虑亚当的评论,它甚至不必达到平方根。一旦你意识到一个数字不能被 3 整除,你可以将你的 top 限制为被 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 个)

1,229 个质数低于 10,000。

于 2021-04-24T23:33:50.047 回答
0

我认为事情的性能问题是由 Lucee 来解决的,而不是你和你的代码。

然而,从这个特定算法的整体性能的角度来看,你能做的最好的经济是循环到sqr(n)+1而不是一路到n。您所做的工作比您需要的要多,与平台差异相比,这对代码性能的贡献更大。

此外,您只需要遍历前面的素数,而不是每个(第二个)数字。这会进一步提高你的表现。

我意识到这个算法只是一个例子,但老实说,其余的不是你可能解决的问题。向 Lucee 提出一张票并等待它被修复(或 DIY,如果你有时间/Java 知识)。

于 2016-05-09T22:09:33.870 回答