Java Stream 性能测试
Java Stream 性能测试
本测试是测试 Java Stream 与传统编程方式(即 foreach)之间的性能差距。
测试环境
JDK
java version "1.8.0_301"
Java(TM) SE Runtime Environment (build 1.8.0_301-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode)
测试框架
JMH v1.33
测试机器
- CPU:AMD Ryzen 7 3700X 8 核 16 线程 4.4GHz
- 内存:8GB * 2 2400MHz
- 操作系统:Linux 5.15.7-1-MANJARO #1 SMP PREEMPT Wed Dec 8 10:09:19 UTC 2021 x86_64 GNU/Linux
测试方式
- 用 maven 把项目打成 jar 包,在命令行界面运行这个 jar 包
- 每个测试项目预热 3 次,每次持续 5 秒
- 每个测试项目运行 5 次,每次持续 5 秒
- 测试结果里的是两种方式以及不同 size 值情况下的平均耗时
- 后面还有根据测试数据所制作的图表,图表中的比值指的是:
Stream方式的平均耗时 / 传统方式的平均耗时
运行命令
java -server -Xms4g -jar stream-demo-1.0-SNAPSHOT-jar-with-dependencies.jar
测试场景
测试数据类:
public class User {
private Integer id;
private String username;
private Boolean sex;
private Integer type;
...
}
场景一
将用户列表转成 id -> username 的映射
测试代码
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 5)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class PerformanceTest {
@Param({
"500", "1000", "1500", "2000", "2500", "3000", "3500", "4000", "4500", "5000",
"10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000", "100000"
})
private int size;
private List<User> users;
@Setup
public void setup() {
users = initUsers(size);
}
/**
* 传统方式
*/
@Benchmark
public Map<Integer, String> tradition() {
Map<Integer, String> map = new HashMap<>((int) (users.size() / 0.75));
for (User user : users) {
map.put(user.getId(), user.getUsername());
}
return map;
}
/**
* Stream方式
*/
@Benchmark
public Map<Integer, String> stream() {
Map<Integer, String> map = users.stream().collect(Collectors.toMap(
User::getId, User::getUsername));
return map;
}
private List<User> initUsers(int size) {
List<User> users = new ArrayList<>();
for (int i = 0; i < size; i++) {
users.add(new User(i, "user" + i, true, 0));
}
return users;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(PerformanceTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
测试结果
Benchmark (size) Mode Cnt Score Error Units
PerformanceTest.stream 500 avgt 5 7.368 ± 0.097 us/op
PerformanceTest.stream 1000 avgt 5 14.940 ± 0.447 us/op
PerformanceTest.stream 1500 avgt 5 19.053 ± 0.761 us/op
PerformanceTest.stream 2000 avgt 5 30.343 ± 0.452 us/op
PerformanceTest.stream 2500 avgt 5 34.554 ± 1.179 us/op
PerformanceTest.stream 3000 avgt 5 38.740 ± 1.548 us/op
PerformanceTest.stream 3500 avgt 5 57.874 ± 2.010 us/op
PerformanceTest.stream 4000 avgt 5 61.074 ± 1.128 us/op
PerformanceTest.stream 4500 avgt 5 64.366 ± 1.613 us/op
PerformanceTest.stream 5000 avgt 5 70.140 ± 0.977 us/op
PerformanceTest.stream 10000 avgt 5 143.495 ± 7.884 us/op
PerformanceTest.stream 20000 avgt 5 288.530 ± 17.670 us/op
PerformanceTest.stream 30000 avgt 5 485.182 ± 14.847 us/op
PerformanceTest.stream 40000 avgt 5 569.877 ± 16.184 us/op
PerformanceTest.stream 50000 avgt 5 861.911 ± 36.345 us/op
PerformanceTest.stream 60000 avgt 5 984.600 ± 24.884 us/op
PerformanceTest.stream 70000 avgt 5 1073.787 ± 42.289 us/op
PerformanceTest.stream 80000 avgt 5 1202.904 ± 41.109 us/op
PerformanceTest.stream 90000 avgt 5 1323.942 ± 23.960 us/op
PerformanceTest.stream 100000 avgt 5 2222.201 ± 71.841 us/op
PerformanceTest.tradition 500 avgt 5 5.911 ± 0.148 us/op
PerformanceTest.tradition 1000 avgt 5 11.346 ± 0.546 us/op
PerformanceTest.tradition 1500 avgt 5 16.598 ± 0.947 us/op
PerformanceTest.tradition 2000 avgt 5 23.989 ± 0.908 us/op
PerformanceTest.tradition 2500 avgt 5 29.481 ± 1.090 us/op
PerformanceTest.tradition 3000 avgt 5 33.921 ± 4.120 us/op
PerformanceTest.tradition 3500 avgt 5 41.820 ± 4.523 us/op
PerformanceTest.tradition 4000 avgt 5 48.667 ± 2.597 us/op
PerformanceTest.tradition 4500 avgt 5 51.205 ± 3.530 us/op
PerformanceTest.tradition 5000 avgt 5 58.111 ± 2.269 us/op
PerformanceTest.tradition 10000 avgt 5 116.051 ± 6.215 us/op
PerformanceTest.tradition 20000 avgt 5 232.722 ± 24.085 us/op
PerformanceTest.tradition 30000 avgt 5 363.922 ± 23.553 us/op
PerformanceTest.tradition 40000 avgt 5 474.173 ± 17.631 us/op
PerformanceTest.tradition 50000 avgt 5 612.063 ± 42.738 us/op
PerformanceTest.tradition 60000 avgt 5 731.101 ± 78.408 us/op
PerformanceTest.tradition 70000 avgt 5 860.554 ± 47.381 us/op
PerformanceTest.tradition 80000 avgt 5 961.721 ± 181.393 us/op
PerformanceTest.tradition 90000 avgt 5 1093.675 ± 67.902 us/op
PerformanceTest.tradition 100000 avgt 5 1309.866 ± 43.078 us/op
图表




场景二
将用户列表转成 VO 列表
测试代码
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 5)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class PerformanceTest {
@Param({
"500", "1000", "1500", "2000", "2500", "3000", "3500", "4000", "4500", "5000",
"10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000", "100000"
})
private int size;
private List<User> users;
@Setup
public void setup() {
users = initUsers(size);
}
/**
* 传统方式
*/
@Benchmark
public List<UserVO> tradition() {
List<UserVO> userVOList = new ArrayList<>(users.size());
for (User user : users) {
userVOList.add(toUserVo(user));
}
return userVOList;
}
/**
* Stream方式
*/
@Benchmark
public List<UserVO> stream() {
List<UserVO> userVoList = users.stream()
.map(this::toUserVo)
.collect(Collectors.toList());
return userVoList;
}
private UserVO toUserVo(User user) {
UserVO userVO = new UserVO();
userVO.setId(user.getId());
userVO.setUsername(user.getUsername());
userVO.setSex(getSexStr(user.getSex()));
userVO.setType(getTypeStr(user.getType()));
return userVO;
}
private String getSexStr(Boolean sex) {
if (sex == null) return "";
return sex ? "男" : "女";
}
private String getTypeStr(Integer type) {
if (type == null) return "";
switch (type) {
case 0:
return "青铜用户";
case 1:
return "白银用户";
case 2:
return "黄金用户";
default:
return "";
}
}
private List<User> initUsers(int size) {
List<User> users = new ArrayList<>();
for (int i = 0; i < size; i++) {
users.add(new User(i, "user" + i, true, 0));
}
return users;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(PerformanceTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
测试结果
Benchmark (size) Mode Cnt Score Error Units
PerformanceTest.stream 500 avgt 5 5.996 ± 0.066 us/op
PerformanceTest.stream 1000 avgt 5 12.553 ± 0.238 us/op
PerformanceTest.stream 1500 avgt 5 17.990 ± 0.517 us/op
PerformanceTest.stream 2000 avgt 5 25.438 ± 0.721 us/op
PerformanceTest.stream 2500 avgt 5 29.965 ± 1.067 us/op
PerformanceTest.stream 3000 avgt 5 35.679 ± 0.844 us/op
PerformanceTest.stream 3500 avgt 5 41.705 ± 2.245 us/op
PerformanceTest.stream 4000 avgt 5 47.160 ± 2.103 us/op
PerformanceTest.stream 4500 avgt 5 54.689 ± 1.613 us/op
PerformanceTest.stream 5000 avgt 5 59.484 ± 1.003 us/op
PerformanceTest.stream 10000 avgt 5 125.990 ± 2.135 us/op
PerformanceTest.stream 20000 avgt 5 237.947 ± 6.158 us/op
PerformanceTest.stream 30000 avgt 5 364.168 ± 7.328 us/op
PerformanceTest.stream 40000 avgt 5 505.319 ± 7.990 us/op
PerformanceTest.stream 50000 avgt 5 629.942 ± 20.899 us/op
PerformanceTest.stream 60000 avgt 5 746.447 ± 26.372 us/op
PerformanceTest.stream 70000 avgt 5 863.620 ± 15.332 us/op
PerformanceTest.stream 80000 avgt 5 1039.621 ± 14.531 us/op
PerformanceTest.stream 90000 avgt 5 1134.118 ± 21.441 us/op
PerformanceTest.stream 100000 avgt 5 1198.103 ± 31.366 us/op
PerformanceTest.tradition 500 avgt 5 4.069 ± 0.053 us/op
PerformanceTest.tradition 1000 avgt 5 8.143 ± 0.085 us/op
PerformanceTest.tradition 1500 avgt 5 12.278 ± 0.268 us/op
PerformanceTest.tradition 2000 avgt 5 16.309 ± 0.297 us/op
PerformanceTest.tradition 2500 avgt 5 20.802 ± 0.855 us/op
PerformanceTest.tradition 3000 avgt 5 24.092 ± 0.146 us/op
PerformanceTest.tradition 3500 avgt 5 28.964 ± 0.252 us/op
PerformanceTest.tradition 4000 avgt 5 32.585 ± 0.533 us/op
PerformanceTest.tradition 4500 avgt 5 37.213 ± 0.533 us/op
PerformanceTest.tradition 5000 avgt 5 41.788 ± 0.668 us/op
PerformanceTest.tradition 10000 avgt 5 83.733 ± 8.949 us/op
PerformanceTest.tradition 20000 avgt 5 167.552 ± 5.889 us/op
PerformanceTest.tradition 30000 avgt 5 246.840 ± 41.616 us/op
PerformanceTest.tradition 40000 avgt 5 311.422 ± 58.097 us/op
PerformanceTest.tradition 50000 avgt 5 373.161 ± 3.911 us/op
PerformanceTest.tradition 60000 avgt 5 464.576 ± 5.978 us/op
PerformanceTest.tradition 70000 avgt 5 524.914 ± 4.203 us/op
PerformanceTest.tradition 80000 avgt 5 624.687 ± 11.820 us/op
PerformanceTest.tradition 90000 avgt 5 700.555 ± 4.651 us/op
PerformanceTest.tradition 100000 avgt 5 864.347 ± 15.987 us/op
图表




场景三
将用户列表的 username 按照在列表中的顺序用逗号拼接起来,并去重
测试代码
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 5)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class PerformanceTest {
@Param({
"500", "1000", "1500", "2000", "2500", "3000", "3500", "4000", "4500", "5000",
"10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000", "100000"
})
private int size;
private List<User> users;
@Setup
public void setup() {
users = initUsers(size);
}
/**
* 传统方式
*/
@Benchmark
public String tradition() {
StringBuilder usernames = new StringBuilder();
Set<String> set = new HashSet<>();
for (User user : users) {
if (set.add(user.getUsername())) {
usernames.append(user.getUsername()).append(',');
}
}
if (usernames.length() != 0) {
usernames.deleteCharAt(usernames.length() - 1);
}
return usernames.toString();
}
/**
* Stream方式
*/
@Benchmark
public String stream() {
String usernames = users.stream()
.map(User::getUsername)
.distinct()
.collect(Collectors.joining(","));
return usernames;
}
private List<User> initUsers(int size) {
List<User> users = new ArrayList<>();
for (int i = 0; i < size; i++) {
users.add(new User(i, "user" + i, true, 0));
}
return users;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(PerformanceTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
测试结果
Benchmark (size) Mode Cnt Score Error Units
PerformanceTest.stream 500 avgt 5 18.733 ± 0.128 us/op
PerformanceTest.stream 1000 avgt 5 36.986 ± 0.688 us/op
PerformanceTest.stream 1500 avgt 5 55.284 ± 2.427 us/op
PerformanceTest.stream 2000 avgt 5 75.768 ± 3.998 us/op
PerformanceTest.stream 2500 avgt 5 97.292 ± 3.165 us/op
PerformanceTest.stream 3000 avgt 5 112.935 ± 3.832 us/op
PerformanceTest.stream 3500 avgt 5 143.662 ± 3.926 us/op
PerformanceTest.stream 4000 avgt 5 157.015 ± 5.791 us/op
PerformanceTest.stream 4500 avgt 5 181.353 ± 3.722 us/op
PerformanceTest.stream 5000 avgt 5 200.123 ± 2.760 us/op
PerformanceTest.stream 10000 avgt 5 421.966 ± 11.457 us/op
PerformanceTest.stream 20000 avgt 5 903.303 ± 9.818 us/op
PerformanceTest.stream 30000 avgt 5 1431.774 ± 11.031 us/op
PerformanceTest.stream 40000 avgt 5 1982.262 ± 9.562 us/op
PerformanceTest.stream 50000 avgt 5 2703.652 ± 47.758 us/op
PerformanceTest.stream 60000 avgt 5 3170.086 ± 164.340 us/op
PerformanceTest.stream 70000 avgt 5 4267.913 ± 121.917 us/op
PerformanceTest.stream 80000 avgt 5 4803.814 ± 96.398 us/op
PerformanceTest.stream 90000 avgt 5 5333.996 ± 57.002 us/op
PerformanceTest.stream 100000 avgt 5 6855.313 ± 40.467 us/op
PerformanceTest.tradition 500 avgt 5 13.903 ± 0.314 us/op
PerformanceTest.tradition 1000 avgt 5 28.263 ± 0.722 us/op
PerformanceTest.tradition 1500 avgt 5 43.187 ± 0.666 us/op
PerformanceTest.tradition 2000 avgt 5 58.980 ± 1.020 us/op
PerformanceTest.tradition 2500 avgt 5 76.938 ± 1.833 us/op
PerformanceTest.tradition 3000 avgt 5 88.327 ± 1.034 us/op
PerformanceTest.tradition 3500 avgt 5 112.626 ± 1.048 us/op
PerformanceTest.tradition 4000 avgt 5 124.694 ± 2.813 us/op
PerformanceTest.tradition 4500 avgt 5 146.171 ± 1.465 us/op
PerformanceTest.tradition 5000 avgt 5 158.249 ± 0.645 us/op
PerformanceTest.tradition 10000 avgt 5 336.988 ± 10.747 us/op
PerformanceTest.tradition 20000 avgt 5 705.727 ± 6.379 us/op
PerformanceTest.tradition 30000 avgt 5 1146.510 ± 7.255 us/op
PerformanceTest.tradition 40000 avgt 5 1496.571 ± 24.538 us/op
PerformanceTest.tradition 50000 avgt 5 2251.932 ± 13.162 us/op
PerformanceTest.tradition 60000 avgt 5 2706.076 ± 37.305 us/op
PerformanceTest.tradition 70000 avgt 5 3424.254 ± 27.254 us/op
PerformanceTest.tradition 80000 avgt 5 3845.747 ± 97.428 us/op
PerformanceTest.tradition 90000 avgt 5 4340.254 ± 26.115 us/op
PerformanceTest.tradition 100000 avgt 5 5540.504 ± 10.432 us/op
图表




场景四
统计整型数组中的偶数个数
测试代码
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 5)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class PerformanceTest {
@Param({
"500", "1000", "1500", "2000", "2500", "3000", "3500", "4000", "4500", "5000",
"10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000", "100000"
})
private int size;
private int[] array;
@Setup
public void setup() {
array = initArray(size);
}
/**
* 传统方式
*/
@Benchmark
public int tradition() {
int count = 0;
for (int i : array) {
if (i % 2 == 0) {
count++;
}
}
return count;
}
/**
* Stream方式
*/
@Benchmark
public int stream() {
long count = Arrays.stream(array)
.filter(i -> i % 2 == 0)
.count();
return (int) count;
}
private int[] initArray(int size) {
int[] array = new int[size];
for (int i = 0; i < size; i++) {
array[i] = i;
}
return array;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(PerformanceTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
测试结果
Benchmark (size) Mode Cnt Score Error Units
PerformanceTest.stream 500 avgt 5 0.475 ± 0.010 us/op
PerformanceTest.stream 1000 avgt 5 0.919 ± 0.010 us/op
PerformanceTest.stream 1500 avgt 5 1.357 ± 0.033 us/op
PerformanceTest.stream 2000 avgt 5 1.788 ± 0.076 us/op
PerformanceTest.stream 2500 avgt 5 2.255 ± 0.007 us/op
PerformanceTest.stream 3000 avgt 5 2.828 ± 0.025 us/op
PerformanceTest.stream 3500 avgt 5 3.115 ± 0.025 us/op
PerformanceTest.stream 4000 avgt 5 3.531 ± 0.031 us/op
PerformanceTest.stream 4500 avgt 5 4.020 ± 0.022 us/op
PerformanceTest.stream 5000 avgt 5 4.491 ± 0.025 us/op
PerformanceTest.stream 10000 avgt 5 9.029 ± 1.425 us/op
PerformanceTest.stream 20000 avgt 5 18.201 ± 0.074 us/op
PerformanceTest.stream 30000 avgt 5 21.745 ± 0.117 us/op
PerformanceTest.stream 40000 avgt 5 30.214 ± 0.241 us/op
PerformanceTest.stream 50000 avgt 5 38.219 ± 2.246 us/op
PerformanceTest.stream 60000 avgt 5 55.953 ± 2.188 us/op
PerformanceTest.stream 70000 avgt 5 60.985 ± 11.136 us/op
PerformanceTest.stream 80000 avgt 5 65.562 ± 53.646 us/op
PerformanceTest.stream 90000 avgt 5 104.806 ± 296.831 us/op
PerformanceTest.stream 100000 avgt 5 141.883 ± 490.840 us/op
PerformanceTest.tradition 500 avgt 5 0.241 ± 0.004 us/op
PerformanceTest.tradition 1000 avgt 5 0.479 ± 0.009 us/op
PerformanceTest.tradition 1500 avgt 5 0.718 ± 0.003 us/op
PerformanceTest.tradition 2000 avgt 5 0.939 ± 0.001 us/op
PerformanceTest.tradition 2500 avgt 5 1.173 ± 0.001 us/op
PerformanceTest.tradition 3000 avgt 5 1.414 ± 0.036 us/op
PerformanceTest.tradition 3500 avgt 5 1.639 ± 0.002 us/op
PerformanceTest.tradition 4000 avgt 5 1.874 ± 0.002 us/op
PerformanceTest.tradition 4500 avgt 5 2.114 ± 0.055 us/op
PerformanceTest.tradition 5000 avgt 5 2.367 ± 0.002 us/op
PerformanceTest.tradition 10000 avgt 5 4.735 ± 0.237 us/op
PerformanceTest.tradition 20000 avgt 5 9.453 ± 0.010 us/op
PerformanceTest.tradition 30000 avgt 5 14.275 ± 0.547 us/op
PerformanceTest.tradition 40000 avgt 5 18.768 ± 0.487 us/op
PerformanceTest.tradition 50000 avgt 5 23.455 ± 1.177 us/op
PerformanceTest.tradition 60000 avgt 5 28.083 ± 0.434 us/op
PerformanceTest.tradition 70000 avgt 5 32.652 ± 0.039 us/op
PerformanceTest.tradition 80000 avgt 5 37.799 ± 0.036 us/op
PerformanceTest.tradition 90000 avgt 5 41.985 ± 0.368 us/op
PerformanceTest.tradition 100000 avgt 5 46.487 ± 0.180 us/op
图表




场景五
跟场景一一样,不过使用的是并行流
测试代码
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 5)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class PerformanceTest {
@Param({
"500", "1000", "1500", "2000", "2500", "3000", "3500", "4000", "4500", "5000",
"10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000", "100000"
})
private int size;
private List<User> users;
@Setup
public void setup() {
users = initUsers(size);
}
/**
* 传统方式
*/
@Benchmark
public Map<Integer, String> tradition() {
Map<Integer, String> map = new HashMap<>((int) (users.size() / 0.75));
for (User user : users) {
map.put(user.getId(), user.getUsername());
}
return map;
}
/**
* Stream方式
*/
@Benchmark
public Map<Integer, String> stream() {
Map<Integer, String> map = users.parallelStream()
.collect(Collectors.toMap(
User::getId, User::getUsername));
return map;
}
private List<User> initUsers(int size) {
List<User> users = new ArrayList<>();
for (int i = 0; i < size; i++) {
users.add(new User(i, "user" + i, true, 0));
}
return users;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(PerformanceTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
测试结果
Benchmark (size) Mode Cnt Score Error Units
PerformanceTest.stream 500 avgt 5 35.249 ± 0.201 us/op
PerformanceTest.stream 1000 avgt 5 50.628 ± 0.142 us/op
PerformanceTest.stream 1500 avgt 5 57.612 ± 0.110 us/op
PerformanceTest.stream 2000 avgt 5 75.033 ± 0.326 us/op
PerformanceTest.stream 2500 avgt 5 86.458 ± 0.305 us/op
PerformanceTest.stream 3000 avgt 5 92.287 ± 0.414 us/op
PerformanceTest.stream 3500 avgt 5 116.306 ± 0.359 us/op
PerformanceTest.stream 4000 avgt 5 125.447 ± 0.174 us/op
PerformanceTest.stream 4500 avgt 5 138.188 ± 0.525 us/op
PerformanceTest.stream 5000 avgt 5 146.119 ± 0.443 us/op
PerformanceTest.stream 10000 avgt 5 267.039 ± 1.097 us/op
PerformanceTest.stream 20000 avgt 5 520.755 ± 4.113 us/op
PerformanceTest.stream 30000 avgt 5 841.691 ± 2.198 us/op
PerformanceTest.stream 40000 avgt 5 1088.443 ± 6.130 us/op
PerformanceTest.stream 50000 avgt 5 1592.737 ± 12.963 us/op
PerformanceTest.stream 60000 avgt 5 1824.027 ± 6.323 us/op
PerformanceTest.stream 70000 avgt 5 2177.562 ± 12.864 us/op
PerformanceTest.stream 80000 avgt 5 2472.056 ± 3.235 us/op
PerformanceTest.stream 90000 avgt 5 2655.888 ± 13.620 us/op
PerformanceTest.stream 100000 avgt 5 3897.188 ± 31.997 us/op
PerformanceTest.tradition 500 avgt 5 5.653 ± 0.099 us/op
PerformanceTest.tradition 1000 avgt 5 10.959 ± 0.219 us/op
PerformanceTest.tradition 1500 avgt 5 17.192 ± 1.095 us/op
PerformanceTest.tradition 2000 avgt 5 21.409 ± 0.627 us/op
PerformanceTest.tradition 2500 avgt 5 28.927 ± 2.463 us/op
PerformanceTest.tradition 3000 avgt 5 32.994 ± 1.276 us/op
PerformanceTest.tradition 3500 avgt 5 42.240 ± 1.316 us/op
PerformanceTest.tradition 4000 avgt 5 47.977 ± 6.044 us/op
PerformanceTest.tradition 4500 avgt 5 52.298 ± 3.606 us/op
PerformanceTest.tradition 5000 avgt 5 62.834 ± 7.198 us/op
PerformanceTest.tradition 10000 avgt 5 117.203 ± 25.916 us/op
PerformanceTest.tradition 20000 avgt 5 236.909 ± 20.363 us/op
PerformanceTest.tradition 30000 avgt 5 367.157 ± 37.229 us/op
PerformanceTest.tradition 40000 avgt 5 491.487 ± 31.215 us/op
PerformanceTest.tradition 50000 avgt 5 609.987 ± 66.807 us/op
PerformanceTest.tradition 60000 avgt 5 717.241 ± 50.279 us/op
PerformanceTest.tradition 70000 avgt 5 869.001 ± 85.684 us/op
PerformanceTest.tradition 80000 avgt 5 974.933 ± 72.376 us/op
PerformanceTest.tradition 90000 avgt 5 1111.963 ± 38.911 us/op
PerformanceTest.tradition 100000 avgt 5 1372.851 ± 53.405 us/op
图表




场景六
跟场景二一样,不过使用的是并行流,并且在 toUserVo 里增加了耗时操作的模拟
测试代码
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 2, time = 30)
@Measurement(iterations = 2, time = 30)
@OutputTimeUnit(TimeUnit.SECONDS)
public class PerformanceTest {
@Param({
"5", "10", "15", "20", "25", "30", "35", "40", "45", "50"
})
private int size;
private List<User> users;
@Setup
public void setup() {
users = initUsers(size);
}
/**
* 传统方式
*/
@Benchmark
public List<UserVO> tradition() {
List<UserVO> userVOList = new ArrayList<>(users.size());
for (User user : users) {
userVOList.add(toUserVo(user));
}
return userVOList;
}
/**
* Stream方式
*/
@Benchmark
public List<UserVO> stream() {
List<UserVO> userVoList = users.parallelStream()
.map(this::toUserVo)
.collect(Collectors.toList());
return userVoList;
}
private UserVO toUserVo(User user) {
UserVO userVO = new UserVO();
// 模拟耗时操作,在我的机器上这段代码的耗时约为100毫秒
// long startAt = System.currentTimeMillis();
for (long i = 0; i < 100000000L; i++) {
userVO.setId(user.getId());
userVO.setUsername(user.getUsername());
userVO.setSex(getSexStr(user.getSex()));
userVO.setType(getTypeStr(user.getType()));
}
// long time = System.currentTimeMillis() - startAt;
// System.out.println("耗时:" + time);
return userVO;
}
private String getSexStr(Boolean sex) {
if (sex == null) return "";
return sex ? "男" : "女";
}
private String getTypeStr(Integer type) {
if (type == null) return "";
switch (type) {
case 0: return "青铜用户";
case 1: return "白银用户";
case 2: return "黄金用户";
default: return "";
}
}
private List<User> initUsers(int size) {
List<User> users = new ArrayList<>();
for (int i = 0; i < size; i++) {
users.add(new User(i, "user" + i, true, 0));
}
return users;
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(PerformanceTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
测试结果
Benchmark (size) Mode Cnt Score Error Units
PerformanceTest.stream 5 avgt 2 0.121 s/op
PerformanceTest.stream 10 avgt 2 0.287 s/op
PerformanceTest.stream 15 avgt 2 1.316 s/op
PerformanceTest.stream 20 avgt 2 0.811 s/op
PerformanceTest.stream 25 avgt 2 1.287 s/op
PerformanceTest.stream 30 avgt 2 2.604 s/op
PerformanceTest.stream 35 avgt 2 1.711 s/op
PerformanceTest.stream 40 avgt 2 3.839 s/op
PerformanceTest.stream 45 avgt 2 3.883 s/op
PerformanceTest.stream 50 avgt 2 3.237 s/op
PerformanceTest.tradition 5 avgt 2 0.578 s/op
PerformanceTest.tradition 10 avgt 2 1.166 s/op
PerformanceTest.tradition 15 avgt 2 1.740 s/op
PerformanceTest.tradition 20 avgt 2 2.304 s/op
PerformanceTest.tradition 25 avgt 2 2.877 s/op
PerformanceTest.tradition 30 avgt 2 3.440 s/op
PerformanceTest.tradition 35 avgt 2 4.045 s/op
PerformanceTest.tradition 40 avgt 2 4.634 s/op
PerformanceTest.tradition 45 avgt 2 5.162 s/op
PerformanceTest.tradition 50 avgt 2 5.801 s/op
图表


总结
- 对于一般场景下的处理,Stream 方式的耗时大概是传统方式的 1.5 倍左右
- 对于基本数据类型的处理,Stream 方式的耗时大概是传统方式在 2 倍左右
- 对于计算量较少的情况,不建议使用并行流
使用 Stream 方式跟传统编程方式相比运行效率之间的差距并不大,除非是对性能要求很高的系统,否则对于一般的业务系统来说不会造成 CPU 的瓶颈,IO 才是最大的瓶颈。相比之下,使用 Stream 可以让代码变得更加干净整洁,可读性和可维护性更好,所以一般情况下推荐使用 Stream 来编程。

浙公网安备 33010602011771号