Groovy收集关于空间/时间的性能考虑 [英] Groovy collections perfomance considerations regarding space/time
问题描述
与普通的Java for-loops相比,Groovys收集方法(关于空间(!)和时间)的性能如何?
例如,对于这种用例:
- sum()与for循环变量
- each()vs. for-循环与变量
- inject()与for循环与变量
- collect()与for-loop与临时集合
- findAll()与带临时集合的for-loop
- find()与for循环与变量
因此,考虑到这些结果,对于关键环境中的Groovy-collection-methods(例如Grails-WebApp)使用for-loops是可取的吗?是否有关于Groovy / Grails性能(优化)的资源?
使用此GBench测试,我得到了以下CPU-时间:
用户系统cpu真实
$ b $循环2578777 67 2578844 2629592
forEachLoop 2027941 47 2027988 2054320
groovySum 3946137 91 3946228 3958705
groovyEach 4703000 0 4703000 4703000
groovyInject 4280792 108 4280900 4352287
导入groovyx.gbench。 BenchmarkBuilder
$ b $ def testSize = 10000
def testSet =(0..testSize)as Set
bm = new BenchmarkBuilder()。run {
'forLoop'{
def n = 0
for(int i = 0; i< testSize; i ++){
n + = i
}
return n
$ b $ forEachLoop'{
def n = 0
for(int i in testSet){
n + = i
}
返回n
}
'groovySum'{
def n = testSet.sum()
return n
}
'groovyEach'{
def n = 0
testSet.each {n + it}
return n
}
'groovyInject'{
def n = testSet.inject(0){el ,总和 - > sum + el}
return n
}
}
bm.prettyPrint()
有趣的基准。毫不奇怪, sum()
更慢。下面是实现的样子:
private static Object sum(Iterable self,Object initialValue,boolean first){
Object result = initialValue;
Object [] param = new Object [1];
for(Object next:self){
param [0] = next;
if(first){
result = param [0];
first = false;
继续;
}
MetaClass metaClass = InvokerHelper.getMetaClass(result);
result = metaClass.invokeMethod(result,plus,param);
}
返回结果;
$ b 正如你所看到的,它必须是通用的,并且使用元编程。结果是更大的时间成本。
您粘贴的基准测试结果是清晰自然的描述。如果你真的需要更好的表现,似乎更好的想法是使用作为
循环。
What is the performance of Groovys collection methods (regarding space(!) and time) in comparison to plain Java for-loops?
Eg for this use cases:
- sum() vs. for-loop with variable
- each() vs. for-loop with variable
- inject() vs. for-loop with variable
- collect() vs. for-loop with temporary collection
- findAll() vs. for-loop with temporary collection
- find() vs. for-loop with variable
So, considering those results, is it advisable to use for-loops over Groovy-collection-methods in critical environments (eg. Grails-WebApp)? Are there resources regarding Groovy/Grails performance (optimization)?
Using this GBench test I got the following results for CPU-time:
user system cpu real
forLoop 2578777 67 2578844 2629592
forEachLoop 2027941 47 2027988 2054320
groovySum 3946137 91 3946228 3958705
groovyEach 4703000 0 4703000 4703000
groovyInject 4280792 108 4280900 4352287
import groovyx.gbench.BenchmarkBuilder
def testSize = 10000
def testSet = (0..testSize) as Set
def bm = new BenchmarkBuilder().run {
'forLoop' {
def n = 0
for(int i = 0; i<testSize; i++) {
n += i
}
return n
}
'forEachLoop' {
def n = 0
for(int i in testSet) {
n += i
}
return n
}
'groovySum' {
def n = testSet.sum()
return n
}
'groovyEach' {
def n = 0
testSet.each { n + it }
return n
}
'groovyInject' {
def n = testSet.inject(0) { el, sum -> sum + el }
return n
}
}
bm.prettyPrint()
解决方案 Interesting benchmark. No surprise that sum()
is slower. Here's how implementation looks like:
private static Object sum(Iterable self, Object initialValue, boolean first) {
Object result = initialValue;
Object[] param = new Object[1];
for (Object next : self) {
param[0] = next;
if (first) {
result = param[0];
first = false;
continue;
}
MetaClass metaClass = InvokerHelper.getMetaClass(result);
result = metaClass.invokeMethod(result, "plus", param);
}
return result;
}
As You can see it must be generic and uses meta programming. The result is bigger time cost.
The results of the benchmark You pasted are clear and pretty self descriptive. If You really need better performance it seems that better idea is to use for
loops.
这篇关于Groovy收集关于空间/时间的性能考虑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!