java基准测试
让我们的产品所有者有一天变得疯狂,并要求您执行以下操作:
From a set of Strings as follows :
“ marco_8”,“ john_33”,“ marco_1”,“ john_33”,“ thomas_5”,“ john_33”,“ marco_4”,...。
给我一个逗号分隔的字符串,其中只包含marco的数字,并且数字需要按顺序排列。
预期结果的示例:“ 1,4,8”
我将以4种不同的方式实现此逻辑,并且将对其中的每一种进行微基准测试。 我要实现逻辑的方法是:
- 传统的Java与循环和所有。
- 可与番石榴一起使用
- 可与Java 8流一起使用
- 与Java 8 parallelStream一起使用
代码在下面或
package com.marco.brownbag.functional;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Ordering;
public class MicroBenchMarkFunctional {private static final int totStrings = 2;public static void main(String[] args) {Set<String> someNames = new HashSet<String>();init(someNames);for (int i = 1; i < totStrings; i++) {someNames.add("marco_" + i);someNames.add("someone_else_" + i);}System.out.println("start");run(someNames);}private static void run(Set<String> someNames) {System.out.println("========================");long start = System.nanoTime();int totalLoops = 20;for (int i = 1; i < totalLoops; i++) {classic(someNames);}System.out.println("Classic : " + ((System.nanoTime() - start)) / totalLoops);start = System.nanoTime();for (int i = 1; i < totalLoops; i++) {guava(someNames);}System.out.println("Guava : " + ((System.nanoTime() - start)) / totalLoops);start = System.nanoTime();for (int i = 1; i < totalLoops; i++) {stream(someNames);}System.out.println("Stream : " + ((System.nanoTime() - start)) / totalLoops);start = System.nanoTime();for (int i = 1; i < totalLoops; i++) {parallelStream(someNames);}System.out.println("Parallel Stream : " + ((System.nanoTime() - start)) / totalLoops);System.out.println("========================");}private static void init(Set<String> someNames) {someNames.add("marco_1");classic(someNames);guava(someNames);stream(someNames);parallelStream(someNames);someNames.clear();}private static String stream(Set<String> someNames) {return someNames.stream().filter(element -> element.startsWith("m")).map(element -> element.replaceAll("marco_", "")).sorted().collect(Collectors.joining(","));}private static String parallelStream(Set<String> someNames) {return someNames.parallelStream().filter(element -> element.startsWith("m")).map(element -> element.replaceAll("marco_", "")).sorted().collect(Collectors.joining(","));}private static String guava(Set<String> someNames) {return Joiner.on(',').join(Ordering.from(String.CASE_INSENSITIVE_ORDER).immutableSortedCopy(Collections2.transform(Collections2.filter(someNames, Predicates.containsPattern("marco")), REPLACE_MARCO)));}private static Function<String, String> REPLACE_MARCO = new Function<String, String>() {@Overridepublic String apply(final String element) {return element.replaceAll("marco_", "");}};private static String classic(Set<String> someNames) {List<String> namesWithM = new ArrayList<String>();for (String element : someNames) {if (element.startsWith("m")) {namesWithM.add(element.replaceAll("marco_", ""));}}Collections.sort(namesWithM);StringBuilder commaSeparetedString = new StringBuilder();Iterator<String> namesWithMIterator = namesWithM.iterator();while (namesWithMIterator.hasNext()) {commaSeparetedString.append(namesWithMIterator.next());if (namesWithMIterator.hasNext()) {commaSeparetedString.append(",");}}return commaSeparetedString.toString();}
}
在深入探讨性能之前,请注意以下两点:
- 忘记init()方法,那只是初始化jvm中的对象,否则数字简直是疯了。
- Java 8的功能风格看起来比番石榴更好,也比以传统方式开发的更干净!
性能:
在具有4核的mac上运行该程序,结果如下:
========================
Classic : 151941400
Guava : 238798150
Stream : 151853850
Parallel Stream : 55724700
========================
并行流快3倍 。 这是因为Java会将作业拆分为多个任务(任务的总和取决于您的计算机,内核等)并将并行运行它们,最后汇总结果。
经典Java和Java 8流具有大致相同的性能。
番石榴更宽松。
这太了不起了,所以有人会想: “太酷了,我可以一直使用parallelStream,到年底我将获得丰厚的回报”。
但是生活绝非易事。 当您将该字符串集从200.000减少到20时,会发生以下情况:
========================
Classic : 36950
Guava : 69650
Stream : 29850
Parallel Stream : 143350
========================
并行流变得非常慢。 这是因为parallelStream在初始化和管理多任务以及组合结果方面有很大的开销。
现在,Java 8流看上去是赢家,而其他2种则胜出。
好的,在这一点上,有人可以说: “对于具有很多元素的集合,我使用parallelStream,否则我使用stream。”
那将很容易获得,但是当我再次将Set从20减少到2时会发生什么呢?
这个 :
========================
Classic : 8500
Guava : 20050
Stream : 24700
Parallel Stream : 67850
========================
经典的Java循环使用很少的元素会更快。
因此,在这一点上,我可以回到疯狂的产品所有者那里,询问他认为该输入集合中有多少个String。 20吗 减? 更多? 多得多?
就像木匠说的: 两次测量,一次切割!
翻译自: https://www.javacodegeeks.com/2014/09/friday-benchmarking-functional-java.html
java基准测试