标签: jmh

Java 8 性能的经典单例与惰性

最近读了一篇文章《Be Lazy With Java 8》 ”,其中介绍了一种创建惰性对象(在第一次访问时创建其内部状态的对象)的方法。

\n\n
public final class Lazy<T> {\n\n    private volatile T value;\n\n    public T getOrCompute(Supplier<T> supplier){\n        final T result = value;\n        return result == null ? maybeCompute(supplier) : result;\n    }\n\n    private synchronized T maybeCompute(Supplier<T> supplier) {\n        if (value == null){\n            value = Objects.requireNonNull(supplier.get());\n        }\n        return value;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我发现这个模式与众所周知的单例模式非常相似,除了泛型之外:

\n\n
public class PropertiesSingleton {\n\n    public static Properties getProperties(){\n        return Helper.INSTANCE;\n    }\n\n    private final static class Helper{\n        private final static Properties INSTANCE = computeWithClassLoaderLock();\n\n\n        private static …
Run Code Online (Sandbox Code Playgroud)

performance java-8 jmh

5
推荐指数
1
解决办法
2172
查看次数

为什么在某些情况下 Java Stream.forEach 方法比其他循环更快?

我目前正在开展一个项目,使用 Java Microbenchmark Harness (JMH) 框架来测量 Java 中不同类型循环的速度。我得到了一些关于流的有趣结果,我无法解释这些结果,并且想知道更好地理解流和数组列表的人是否可以帮助我解释我的结果。

基本上,当迭代大小为 100 左右的数组列表时,stream.forEach 方法比任何其他类型的循环快得多:

我的结果图表如下所示: https ://i.stack.imgur.com/W34eA.png

我尝试过使用对象和字符串的数组列表,并且都产生类似的结果。随着列表的大小变大,流方法仍然更快,但其他列表之间的性能差距变得更小。我不知道是什么导致了这些结果。

@Fork(5)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class StackOverflowQ {

    List<Integer> intList;

    int size = 100;

    @Setup
    public void setup() {
        intList = new ArrayList<>(size);
        for(int i = 0; i<size;i++){
            intList.add(i);
        }
    }

    /**
     Work done to each item in the loop.
     */
    public double doWork(int item) { …
Run Code Online (Sandbox Code Playgroud)

java loops for-loop java-stream jmh

5
推荐指数
1
解决办法
6976
查看次数

如何使用 JMH 测量平均冷启动时间?

在 JMH(Java Microbenchmark Harness)中,我们可以使用

@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 10)
@Measurement(iterations = 10)
Run Code Online (Sandbox Code Playgroud)

评估 JVM 预热后执行的平均时间。

我们也可以使用

@BenchmarkMode(Mode.SingleShotTime)
@Measurement(iterations = 1)
Run Code Online (Sandbox Code Playgroud)

估计执行的冷启动时间。但这只会执行一次基准测试,这可能会引入偏差。那么有没有什么方法可以评估JMH中冷启动的平均时间呢?

java benchmarking jmh

5
推荐指数
1
解决办法
130
查看次数

数组循环,索引循环和增强循环之间的性能差异

JLS指出,对于数组,“增强的for语句相当于以下形式的基本 for 语句”。但是,如果我检查 JDK8 生成的字节码,对于两种变体都会生成不同的字节码,并且如果我尝试测量性能,令人惊讶的是,增强的字节码似乎给出了更好的结果(在 jdk8 上)...有人可以建议为什么吗? \是吗?我猜这是因为 jmh 测试不正确,所以如果是这样,请建议如何解决这个问题。(我知道 JMH 声明不要使用循环进行测试,但我认为这不适用于此处,因为我实际上是在尝试测量此处的循环)

\n

我的 JMH 测试相当简单(可能太简单了),但我无法解释结果。测试JMH代码如下,典型结果为:

\n
JdkBenchmarks.enhanced  avgt    5  2556.281 \xc2\xb1  31.789  ns/op\nJdkBenchmarks.indexed   avgt    5  4032.164 \xc2\xb1 100.121  ns/op\n
Run Code Online (Sandbox Code Playgroud)\n

这意味着通常增强的 for 循环速度更快,并且其测量比索引循环更准确,因此我们无法解决测量不确定性的差异。原则上,对于使用随机整数初始化的数组或更大的数组,结果相同。

\n
public class JdkBenchmarks {\n\n    @Benchmark\n    @BenchmarkMode(AverageTime)\n    @OutputTimeUnit(NANOSECONDS)\n    public void indexed(Blackhole blackhole, TestState testState) {\n        int length = testState.values.length;\n        for(int i = 0; i < length; i++) {\n            blackhole.consume(testState.values[i]);\n        }\n    }\n\n    @Benchmark\n    @BenchmarkMode(AverageTime)\n    @OutputTimeUnit(NANOSECONDS)\n    public void enhanced(Blackhole blackhole, TestState testState) {\n        for …
Run Code Online (Sandbox Code Playgroud)

java jmh

5
推荐指数
1
解决办法
1150
查看次数

Java Microbenchmark Harness 出现错误无法找到资源:/META-INF/BenchmarkList

我想用 JMH 来衡量斐波那契函数的性能。但编译时出现以下错误:

Exception in thread "main" java.lang.RuntimeException: ERROR: Unable to find the resource: /META-INF/BenchmarkList
    at jmh.core@1.34/org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:98)
    at jmh.core@1.34/org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:124)
    at jmh.core@1.34/org.openjdk.jmh.runner.Runner.internalRun(Runner.java:253)
    at jmh.core@1.34/org.openjdk.jmh.runner.Runner.run(Runner.java:209)
    at jmh.core@1.34/org.openjdk.jmh.Main.main(Main.java:71)
    at project/Mypackage.BenchmarkRunner.main(BenchmarkRunner.java:6)
Run Code Online (Sandbox Code Playgroud)

我使用 IntelliJ IDEA 我使用 openJDK 16

我尝试在资源目录中添加文件夹和文件/META-INF/BenchmarkList 我遇到此错误:

No matching benchmarks. Miss-spelled regexp?
Use EXTRA verbose mode to debug the pattern matching.
Run Code Online (Sandbox Code Playgroud)

我的主要课程开始基准测试:

Exception in thread "main" java.lang.RuntimeException: ERROR: Unable to find the resource: /META-INF/BenchmarkList
    at jmh.core@1.34/org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:98)
    at jmh.core@1.34/org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:124)
    at jmh.core@1.34/org.openjdk.jmh.runner.Runner.internalRun(Runner.java:253)
    at jmh.core@1.34/org.openjdk.jmh.runner.Runner.run(Runner.java:209)
    at jmh.core@1.34/org.openjdk.jmh.Main.main(Main.java:71)
    at project/Mypackage.BenchmarkRunner.main(BenchmarkRunner.java:6)
Run Code Online (Sandbox Code Playgroud)

以及我想要衡量其性能的斐波那契方法的课程

No matching benchmarks. Miss-spelled …
Run Code Online (Sandbox Code Playgroud)

java microbenchmark jmh

5
推荐指数
1
解决办法
1257
查看次数

使用 JMH 得到:错误:传输错误 202:连接失败:连接被拒绝

友好的问候。\n我在使用 JMH 时遇到一个非常奇怪的问题。这里\xef\xbc\x9a

\n
ERROR: transport error 202: connect failed: Connection refused\nERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)\nJDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [./src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c:735]\n<forked VM failed with exit code 2>\n<stdout last='20 lines'>\n</stdout>\n<stderr last='20 lines'>\ntransport error 202: connect failed: Connection refused\n\nOpenJDK 64-Bit Server VM warning: -XX:ThreadPriorityPolicy=1 may require system level permission, e.g., being the root user. If the necessary permission is not possessed, changes to priority will be silently ignored.\nERROR: transport error 202: connect failed: Connection refused\nERROR: JDWP Transport …
Run Code Online (Sandbox Code Playgroud)

java gradle jmh

5
推荐指数
0
解决办法
502
查看次数

JIT 预热后,如何使 ByteBuffer 与直接 byte[] 访问一样高效?

我正在尝试优化一个简单的解压缩例程,并遇到了这个奇怪的性能怪癖,我似乎找不到太多信息:手动实现的简单字节缓冲区比内置字节缓冲区(堆)快 10%-20% & 映射)用于简单操作(读取一个字节,读取 n 个字节,是否是流末尾)

\n

我测试了3个API:

\n
    \n
  • 方法ByteBuffer.wrap(byte[])
  • \n
  • 原始字节[]访问
  • \n
  • 字节访问的简单包装器上的方法(大部分)镜像 ByteBuffer API
  • \n
\n

简单的包装器:

\n
class TestBuf {\n    private final byte[] ary;\n    private int pos = 0;\n\n    public TestBuf(ByteBuffer buffer) {  // ctor #1\n        ary = new byte[buffer.remaining()];\n        buffer.get(ary);\n    }\n    \n    public TestBuf(byte[] inAry) { // ctor #2\n        ary = inAry;\n    }\n\n    public int readUByte() { return ary[pos++] & 0xFF; }\n\n    public boolean hasRemaining() { return pos < ary.length; }\n\n    public void get(byte[] …
Run Code Online (Sandbox Code Playgroud)

java performance jvm bytebuffer jmh

5
推荐指数
1
解决办法
721
查看次数

基准结果ForkJoin vs Disruptor?

我已经运行了这个DisruptovsFJ Mirco-Benchmarks Aleskey Shipilev,其中ForkJoin和Disruptor库的性能进行了比较.

我在Linux平台i5上使用JDK1.8.40的结果:

Benchmark                     Score,     Score Error (99.9%),Unit,Param: slicesK,

Disruptor.run,              939.801405,   20.741961,ms/op,   50000,0,10
ForkJoin.run,               1175.263451,  0.595711, ms/op,   50000,0,10
ForkJoinRecursive.run       771.854028,   26.022542,ms/op,   50000,0,10
ForkJoinRecursiveDeep.run,  1356.697011,  28.666325,ms/op,   50000,0,10
ForkJoinReuse.run,          7974.180793,  49.604539,ms/op,   50000,0,10 
Run Code Online (Sandbox Code Playgroud)

slicesK < 50000预期结果的第一部分Disruptor是使用RingBuffer和一种使其在并发上下文中高效的机制.

现在,当slicesK >= 50000Disruptor测试比ForkJoinRecursiveDeep,并ForkJoinReuse少高性能.有人可以向我解释那些结果吗?谢谢

jmh

4
推荐指数
1
解决办法
522
查看次数

从jar运行特定的JMH基准测试

我有几个使用@Benchmark注释的重型基准类.在使用基准测试建立jar后,我可以使用以下命令运行所有这些

java -Xmx4G -jar benchmarks.jar -f 1 -wi 3 -i 10
Run Code Online (Sandbox Code Playgroud)

如果我不想运行所有这些基准测试,如何指定运行基准?

java jmh

4
推荐指数
2
解决办法
2142
查看次数

模运算符和按位AND的性能比较

我正在努力确定32位整数是偶数还是奇数.我设置了两种方法:

模数(%)方法

int r = (i % 2);
Run Code Online (Sandbox Code Playgroud)

按位(&)方法

int r = (i & 0x1);
Run Code Online (Sandbox Code Playgroud)

两种方法都成功运作.所以我每行运行15000次来测试性能.

结果:

模数(%)方法(源代码)

意思是141.5801887ns | SD 270.0700275ns

按位(&)方法(源代码)

意思是141.2504ns | SD 193.6351007ns

问题:

为什么按位(&)比除法(%)更稳定?

JVM是否根据此处使用AND(&)优化模数(%)?

java performance bit-manipulation jmh

4
推荐指数
1
解决办法
295
查看次数