sleep(0) benchmark

209 阅读1分钟

jmh依赖

引入jmh依赖

<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.23</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.23</version>
    <scope>provided</scope>
</dependency>

code

package com.example.test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations =3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations =5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(4)
public class sleepTest {
  public static AtomicInteger num= new AtomicInteger(0);
  @Benchmark
  public AtomicInteger intTest() {
    for (int i = 0; i < 262144; i++) {
      num.getAndAdd(1);
    }
    return num;
  }
  @Benchmark
  public AtomicInteger longTest() {
    for (long i = 0; i < 262144; i++) {
      num.getAndAdd(1);
    }
    return num;
  }
  @Benchmark
  public AtomicInteger div() {
    for (int i = 0; i < 262144; i++) {
      num.getAndAdd(1);
      if (i % 1000 == 0)
      {
        try {
          Thread.sleep(0);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
    return num;
  }

  @Benchmark
  public AtomicInteger sleep() {
    for (int i = 0; i < 262144; i++) {
      num.getAndAdd(1);
      try {
        Thread.sleep(0);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    return num;
  }
  public static void main(String[] args) throws Exception {
    Options opts = new OptionsBuilder()
        .include(sleepTest.class.getSimpleName())
        .resultFormat(ResultFormatType.JSON)
        .build();
    new Runner(opts).run();
  }
}

结果

我分别使用了两个jdk的版本来进行了测试

jdk 1.8

JMH version: 1.23
VM version: JDK 1.8.0_241, Java HotSpot(TM) 64-Bit Server VM, 25.241-b07

image.png

jdk 17

JMH version: 1.23
VM version: JDK 17.0.4.1, OpenJDK 64-Bit Server VM, 17.0.4.1+9-LTS

image.png

分析

  • intTest 循环变量为int,在jdk17版本中由于对于countloop有了优化,所以性能最高
  • sleep 循环变量为int 每一次循环都sleep(0),频繁gc,所以性能最差
  • div 循环变量为int 1000次循环执行一次sleep(0),相对比来说 jdk8的时候比longTest高,jdk17的时候,比longTest低
  • longTest 循环变量为long

总结

从我这次简单的测试来说,似乎选择long还是说继续保持sleep(0)的方式,好像没有太大的差别,当然我这测试不是非常严谨,所以仅供参考