JMH迭代从> 300,000 ops / sec变为< 1 op / sec

时间:2015-10-25 19:16:42

标签: java concurrenthashmap jmh java-threads

我的主类包含多个线程使用的数据结构。在我原来的程序中,我也在这里启动线程。

public class JDKSolution {

public static final ConcurrentHashMap<Long, Book> books = new ConcurrentHashMap<>();
public static void main(String[] args) throws RunnerException{
    Options opt = new OptionsBuilder()
        .include(JDKSolutionThread.class.getSimpleName())
        .forks(1)
        .jvmArgsAppend("-XX:MaxInlineLevel=12")
        .verbosity(VerboseMode.EXTRA)
        .build();

    new Runner(opt).run();              
}
}

书就是

public class Book {
  static long count  = 0;
  long id;
  Book(){
    synchronized(this){
      id = count;
      count++;
    }
  }

  long getID(){
    return id;
  }
}

我有另一个扩展线程的类;这里是要分析的方法。

@State(Scope.Benchmark)
public class JDKSolutionThread extends Thread{

@Benchmark 
    public void addBook(){
        Book b = new Book();
        books.put(b.getID(), b);
    }
}

输出看起来像这样

# Warmup Iteration  15: 329731.671 ops/s
# Warmup Iteration  16: 23160.167 ops/s
# Warmup Iteration  17: 55316.913 ops/s
# Warmup Iteration  18: 30454.814 ops/s
# Warmup Iteration  19: 0.316 ops/s
# Warmup Iteration  20: 0.880 ops/s
Iteration   1: 0.085 ops/s
Iteration   2: 1.349 ops/s
...
Iteration  20: 4.508 ops/s
<JMH had finished, but forked VM did not exit, are there stray running threads? Waiting 24 seconds more...>
Thread[DestroyJavaVM,5,main]
  at java.lang.Object.wait(Native Method)
  at java.lang.Thread.join(Thread.java:1245)
  at java.lang.Thread.join(Thread.java:1319)
  at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106)
  at java.lang.ApplicationShutdownHooks$1.run(ApplicationShutdownHooks.java:46)
  at java.lang.Shutdown.runHooks(Shutdown.java:123)
  at java.lang.Shutdown.sequence(Shutdown.java:167)
  at java.lang.Shutdown.shutdown(Shutdown.java:234)

Thread[Thread-0,5,main]
  at java.lang.StringCoding.deref(StringCoding.java:63)
  at java.lang.StringCoding.encode(StringCoding.java:330)
  at java.lang.String.getBytes(String.java:918)
  at java.io.UnixFileSystem.getBooleanAttributes0(Native Method)
  at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:242)
  at java.io.File.exists(File.java:819)
  at sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:1245)
  at sun.misc.URLClassPath.getResource(URLClassPath.java:212)
  at java.net.URLClassLoader$1.run(URLClassLoader.java:365)
  at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
  at org.openjdk.jmh.runner.link.BinaryLinkClient.close(BinaryLinkClient.java:141)
  at org.openjdk.jmh.runner.ForkedMain.hangup(ForkedMain.java:136)
  at org.openjdk.jmh.runner.ForkedMain$HangupThread.run(ForkedMain.java:157)

<shutdown timeout of 30 seconds expired, forcing forked VM to exit>

每秒的操作应该在每次迭代约300000的范围内。什么会导致1次操作?

1 个答案:

答案 0 :(得分:3)

在大多数基准测试模式中,JMH反复调用@Benchmark

假设books是一个集合,那么您将使集合饱和,并且每个put调用都会添加到越来越大的集合中。您必须在达到某个尺寸后清除集合,或者在Book之后删除其他put以保持不变的大小,或者将集合模拟为&#34;跳过&#34;所有这些措施都会对实验设计和实验数据产生影响,因此您有责任选择并面对后果。