我偶然发现了一个非常不稳定的性能曲线实例,它对原始数组进行了非常简单的map/reduce操作.这是我的jmh基准代码:
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
@OperationsPerInvocation(Measure.ARRAY_SIZE)
@Warmup(iterations = 300, time = 200, timeUnit=MILLISECONDS)
@Measurement(iterations = 1, time = 1000, timeUnit=MILLISECONDS)
@State(Scope.Thread)
@Threads(1)
@Fork(1)
public class Measure
{
static final int ARRAY_SIZE = 1<<20;
final int[] ds = new int[ARRAY_SIZE];
private IntUnaryOperator mapper;
@Setup public void setup() {
setAll(ds, i->(int)(Math.random()*(1<<7)));
final int multiplier = (int)(Math.random()*10);
mapper = d -> multiplier*d;
}
@Benchmark public double multiply() {
return Arrays.stream(ds).map(mapper).sum();
}
}
Run Code Online (Sandbox Code Playgroud)
以下是典型输出的片段:
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/bin/java
# VM options: <none>
# Warmup: 300 iterations, …Run Code Online (Sandbox Code Playgroud) 我有这段代码做范围最小查询.当t = 100000时,i和j总是在每个输入行中改变,它在Java 8u60中的执行时间约为12秒.
for (int a0 = 0; a0 < t; a0++) {
String line = reader.readLine();
String[] ls = line.split(" ");
int i = Integer.parseInt(ls[0]);
int j = Integer.parseInt(ls[1]);
int min = width[i];
for (int k = i + 1; k <= j; k++) {
if (min > width[k]) {
min = width[k];
}
}
writer.write(min + "");
writer.newLine();
}
Run Code Online (Sandbox Code Playgroud)
当我提取新方法以找到最小值时,执行时间快4倍(约2.5秒).
for (int a0 = 0; a0 < t; a0++) {
String line = reader.readLine();
String[] …Run Code Online (Sandbox Code Playgroud) 我在lambda vs方法参考上运行了一些JMH测试,看起来类似于:
IntStream......reduce(Integer::max)
vs.
IntSream.......reduce((i1, i2) -> Integer.max(i1, i2))
Run Code Online (Sandbox Code Playgroud)
我注意到的是,与Java中的lambda相比,方法引用的执行速度大约是lambda的5倍。当我在Java 11中运行测试时,两种方法的执行时间都与Java中方法引用的执行速度差不多。 8.因此,Java 11中的lambda和方法引用之间在性能上没有重大区别。
我的问题是:从Java 8到11进行了哪些改进以提高性能?我正在使用OpenJDK。
编辑我的基准:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 1, jvmArgs = {"-XX:CompileThreshold=5000"})
@Warmup(iterations = 2)
public class FindMaxInt {
@Param({"10000", "1000000", "10000000"})
private int n;
private List<Integer> data;
@Setup
public void setup(){
data = createData();
}
@Benchmark
public void streamWithMethodReference(final Blackhole blackhole){
int max = data.stream().mapToInt(Integer::intValue).reduce(Integer.MIN_VALUE, Integer::max);
blackhole.consume(max);
}
@Benchmark
public void streamWithLambda(final Blackhole blackhole){
int max = data.stream().mapToInt(Integer::intValue).reduce(Integer.MIN_VALUE, (i1, i2) -> Integer.max(i1, i2));
blackhole.consume(max);
}
Run Code Online (Sandbox Code Playgroud) 我发现C++编译器这样做但我想知道Java编译器是否也这样做,因为在那个答案中他们说添加静态会这样做但是静态在java和C++中是不同的.在我的情况下表现会重要,因为我使用被称为每帧只有一次在一场比赛中循环,并呼吁无处功能,使其更易于阅读
在我的代码我有它设置了与此类似,只是多了很多电话
while(running)
{
update();
sync();
}
Run Code Online (Sandbox Code Playgroud)
然后update(),render()会调用更多调用其他方法的方法
private final void update()
{
switch(gameState)
{
case 0:
updateMainMenu();
renderMainMenu();
break;
case 1:
updateInGame();
renderInGame();
break;
//and so on
}
}
private final void updateInGame()
{
updatePlayerData();
updateDayCycle();
//and so on
}
private final void updatePlayerData()
{
updateLocation();
updateHealth();
//and so on
}
Run Code Online (Sandbox Code Playgroud)
那么编译器是否会内联这些函数,因为它们只在同一位置每帧使用一次?
如果这是一个不好的问题,请告诉我,我将删除它.
我在解决Euler项目的问题205时发现了这一点.问题如下:
彼得有九个四面(金字塔)骰子,每个骰子都有编号为1,2,3,4的面孔.科林有六个六面(立方体)骰子,每个骰子都有编号为1,2,3,4,5,6的面孔.
彼得和科林掷骰子并比较总数:总得分最高.如果总数相等,结果是平局.
金字塔皮特击败立方科林的可能性是多少?将您的答案四舍五入到0.abcdefg形式的七位小数
我用Guava写了一个天真的解决方案:
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
public class Problem205 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<Integer> peter = Sets.cartesianProduct(Collections.nCopies(9, ImmutableSet.of(1, 2, 3, 4)))
.stream()
.map(l -> l
.stream()
.mapToInt(Integer::intValue)
.sum())
.collect(Collectors.toList());
List<Integer> colin = Sets.cartesianProduct(Collections.nCopies(6, ImmutableSet.of(1, 2, 3, 4, 5, 6)))
.stream()
.map(l -> l
.stream()
.mapToInt(Integer::intValue)
.sum())
.collect(Collectors.toList());
long startTime2 = System.currentTimeMillis();
// IMPORTANT BIT HERE! v
long solutions = …Run Code Online (Sandbox Code Playgroud)