package com.tyndalehouse.step.tools.performance; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; import org.crosswire.jsword.book.BookException; import org.crosswire.jsword.passage.NoSuchKeyException; import com.tyndalehouse.step.core.service.jsword.impl.JSwordPassageServiceImpl; import com.tyndalehouse.step.core.utils.TestUtils; public class PerformancePassageRetrieval { /** * tries to replicate the issue with bookdata not being able to be read in a concurrent fashion * * @throws NoSuchKeyException a no such key exception * @throws BookException a book exception * @throws InterruptedException when the thread is interrupted */ public static void testConcurrencyIssueThroughStep() throws NoSuchKeyException, BookException, InterruptedException { final String[] names = { "KJV", "ESV-THE" }; final String[] ref = { "Rom.2", "John 7", "2Ki.2", "Rom.1;John 4;2Ki.2", "Acts 3:4-6" }; final ThreadMXBean thbean = ManagementFactory.getThreadMXBean(); thbean.setThreadContentionMonitoringEnabled(true); final JSwordPassageServiceImpl jsi = new JSwordPassageServiceImpl( TestUtils.mockVersificationService(), null, null, null, TestUtils.mockVersionResolver(), null); final Queue<Long> times = new ConcurrentLinkedQueue<Long>(); final AtomicLong iterations = new AtomicLong(); final Runnable r1 = new Runnable() { @Override public void run() { for (int ii = 0; ii < 1000; ii++) { final long l = System.currentTimeMillis(); jsi.getOsisText(names[ii % 2], ref[ii % 5]); times.add(System.currentTimeMillis() - l); iterations.incrementAndGet(); } final ThreadInfo threadInfo = thbean.getThreadInfo(new long[] { Thread.currentThread() .getId() }, true, true)[0]; System.err.println("Waited a total of " + threadInfo.getBlockedCount() + " times, resulting in " + threadInfo.getBlockedTime() + "ms wasted time"); } }; int ii = 0; final long start = System.currentTimeMillis(); final List<Thread> threads = new ArrayList<Thread>(); while (ii++ < 16) { final Thread t1 = new Thread(r1); t1.start(); threads.add(t1); } new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(10000); } catch (final InterruptedException e) { e.printStackTrace(); } System.out.println(iterations.get() + " iterations so far"); } } }).start(); for (final Thread t : threads) { t.join(); } final long total = System.currentTimeMillis() - start; System.err.println(String.format("Executed: %d in %d ms, %f ms / iteration", iterations.get(), total, (double) total / (double) iterations.get())); } }