aboutsummaryrefslogtreecommitdiffstats
path: root/src/test/java/com/jsyn/research/BenchMultiThreading.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/jsyn/research/BenchMultiThreading.java')
-rw-r--r--src/test/java/com/jsyn/research/BenchMultiThreading.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/test/java/com/jsyn/research/BenchMultiThreading.java b/src/test/java/com/jsyn/research/BenchMultiThreading.java
new file mode 100644
index 0000000..24624c5
--- /dev/null
+++ b/src/test/java/com/jsyn/research/BenchMultiThreading.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2009 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.research;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+// TODO: Use thread pools, or maybe JMH?
+public class BenchMultiThreading {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BenchMultiThreading.class);
+
+ private static final int FRAMES_PER_BLOCK = 64;
+ int numThreads = 4;
+ int numLoops = 100000;
+ private ArrayList<CustomThread> threadList;
+
+ static class CustomThread extends Thread {
+ long frameCount = 0;
+ long desiredFrame = 0;
+ Object semaphore = new Object();
+ Object goSemaphore = new Object();
+ volatile boolean go = true;
+ long startNano;
+ long stopNano;
+ long maxElapsed;
+
+ @Override
+ public void run() {
+ try {
+ startNano = System.nanoTime();
+ while (go) {
+ // Watch for long delays.
+ stopNano = System.nanoTime();
+ long elapsed = stopNano - startNano;
+ startNano = System.nanoTime();
+ if (elapsed > maxElapsed) {
+ maxElapsed = elapsed;
+ }
+
+ synchronized (semaphore) {
+ // Audio synthesis would occur here.
+ frameCount += 1;
+ // LOGGER.debug( this + " generating frame " +
+ // frameCount );
+ semaphore.notify();
+ }
+ synchronized (goSemaphore) {
+ while (desiredFrame <= frameCount) {
+ goSemaphore.wait();
+ }
+ }
+ long stopNano = System.nanoTime();
+ }
+ } catch (InterruptedException e) {
+ LOGGER.debug("CustomThread interrupted. ");
+ }
+ LOGGER.debug("Finishing " + this);
+ }
+
+ public void abort() {
+ go = false;
+ interrupt();
+ }
+
+ public void waitForFrame(long targetFrame) throws InterruptedException {
+ synchronized (semaphore) {
+ while (frameCount < targetFrame) {
+ semaphore.wait();
+ }
+ }
+ }
+
+ public void generateFrame(long desiredFrame) {
+ synchronized (goSemaphore) {
+ this.desiredFrame = desiredFrame;
+ goSemaphore.notify();
+ }
+ }
+
+ }
+
+ @Test
+ public void testMultiThreads() {
+ threadList = new ArrayList<>();
+ for (int i = 0; i < numThreads; i++) {
+ CustomThread thread = new CustomThread();
+ threadList.add(thread);
+ thread.start();
+ }
+
+ long frameCount = 0;
+ long startTime = System.currentTimeMillis();
+ try {
+ for (int i = 0; i < numLoops; i++) {
+ frameCount += 1;
+ waitForThreads(frameCount);
+ // LOGGER.debug("got frame " + frameCount );
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ long stopTime = System.currentTimeMillis();
+ long elapsedTime = stopTime - startTime;
+ double elapsedSeconds = 0.001 * elapsedTime;
+ double blocksPerSecond = numLoops / elapsedSeconds;
+ System.out.format("blocksPerSecond = %10.3f\n", blocksPerSecond);
+ double framesPerSecond = blocksPerSecond * FRAMES_PER_BLOCK;
+ System.out.format("audio framesPerSecond = %10.3f at %d frames per block\n",
+ framesPerSecond, FRAMES_PER_BLOCK);
+
+ for (CustomThread thread : threadList) {
+ System.out.format("max elapsed time is %d nanos or %f msec\n", thread.maxElapsed,
+ (thread.maxElapsed / 1000000.0));
+ }
+ for (CustomThread thread : threadList) {
+ assertEquals(frameCount, thread.frameCount, "BlockCount must match ");
+ thread.abort();
+ }
+
+ }
+
+ private void waitForThreads(long frameCount) throws InterruptedException {
+ for (CustomThread thread : threadList) {
+ // Ask threads to wake up and generate up to this frame.
+ thread.generateFrame(frameCount);
+ }
+ for (CustomThread thread : threadList) {
+ // Wait for all the threads to catch up.
+ thread.waitForFrame(frameCount);
+ }
+ }
+}