以下用于查找素数的代码在Adobe ColdFusion(10)和Lucee(4.5)之间的性能差别很大。在同一台机器上测试(6C i7 3930k @ 4 GHz,Windows 10 64 Bit,两个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
stopIndex @ 20k
stopIndex @ 30k
trycf.com
和cflive.net
显示出类似的差距。
我检查了cfscript(与标签)是否对时间有影响,但是没有。与CFML引擎相关的服务器设置似乎也没有任何明显的影响。
性能差异可能是什么原因?
我怎么可能解决这个问题?
背景:我正在生产服务器上运行繁重的数学操作(几何,图像渲染),这正好运行Lucee,并注意到性能低下。
答案 0 :(得分:1)
整数数学比浮点数学慢,所以由于Lucee将变量存储为类型的方式,因此运行速度较慢。如果强制n为非整数Lucee运行速度快4倍
if ((n+1.0) % d == 0) {
此调整也使ACF的速度提高了一倍以上
答案 1 :(得分:0)
我认为性能问题的一面是由Lucee修复,而不是你和你的代码。
然而,从这个特定算法的整体表现来看,他们最经济的就是循环到sqr(n)+1
而不是一直到n
。你做的工作比你需要的更多,而且这个代码的性能比平台差异更大。
此外,您只需要遍历前面的素数,而不是每个(第二个)数字。这可以进一步提高您的表现。
我意识到这个算法只是一个例子,但老实说其余部分并不是你能够解决的问题。与Lucee一起提出一张票并等待它被修复(如果你有时间/ Java知识,可以DIY)。
答案 2 :(得分:0)
我知道这不是在回答问题,但进一步考虑亚当的评论,它甚至不必达到平方根。一旦您意识到一个数不能被 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 个素数。