summaryrefslogtreecommitdiffstats
path: root/test/114-ParallelGC
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-07-26 01:13:13 -0700
committerAndreas Gampe <agampe@google.com>2014-07-26 01:38:33 -0700
commit93f3da1578bf25d3bc8cf1d121477bf29b4d760a (patch)
tree379f11e1f9d52769e9b3b8cdb9d265b7830caffd /test/114-ParallelGC
parent3bcac48f23094fa0f46315a080ec47fc368fd4c2 (diff)
downloadart-93f3da1578bf25d3bc8cf1d121477bf29b4d760a.tar.gz
art-93f3da1578bf25d3bc8cf1d121477bf29b4d760a.tar.bz2
art-93f3da1578bf25d3bc8cf1d121477bf29b4d760a.zip
ART: Rewrite ParallelGC run-test
To better test what ParallelGC is intended to do, write a version that will more fairly allocate objects between the threads, and will let each thread OOM only once. Use a barrier to wait for completion of all threads, and force a final GC by allocating some more objects. Bug: 16406852 Change-Id: I019ddc08515b9610c18d55280cd46cbe3ae3e5ac
Diffstat (limited to 'test/114-ParallelGC')
-rw-r--r--test/114-ParallelGC/src/Main.java122
1 files changed, 111 insertions, 11 deletions
diff --git a/test/114-ParallelGC/src/Main.java b/test/114-ParallelGC/src/Main.java
index 15d5e50796..8e2519dd0a 100644
--- a/test/114-ParallelGC/src/Main.java
+++ b/test/114-ParallelGC/src/Main.java
@@ -16,38 +16,138 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class Main implements Runnable {
+
+ public final static long TIMEOUT_VALUE = 5; // Timeout in minutes.
+ public final static long MAX_SIZE = 1000; // Maximum size of array-list to allocate.
+
public static void main(String[] args) throws Exception {
Thread[] threads = new Thread[16];
+
+ // Use a cyclic system of synchronous queues to pass a boolean token around.
+ //
+ // The combinations are:
+ //
+ // Worker receives: true false false true
+ // Worker has OOM: false false true true
+ // |
+ // v
+ // Value to pass: true false false false
+ // Exit out of loop: false true true true
+ // Wait on in queue: true false false true
+ //
+ // Finally, the workers are supposed to wait on the barrier to synchronize the GC run.
+
+ CyclicBarrier barrier = new CyclicBarrier(threads.length);
+ List<SynchronousQueue<Boolean>> queues = new ArrayList<SynchronousQueue<Boolean>>(
+ threads.length);
+ for (int i = 0; i < threads.length; i++) {
+ queues.add(new SynchronousQueue<Boolean>());
+ }
+
for (int i = 0; i < threads.length; i++) {
- threads[i] = new Thread(new Main(i));
+ threads[i] = new Thread(new Main(i, queues.get(i), queues.get((i + 1) % threads.length),
+ barrier));
}
for (Thread thread : threads) {
thread.start();
}
+
+ // Push off the cycle.
+ checkTimeout(queues.get(0).offer(Boolean.TRUE, TIMEOUT_VALUE, TimeUnit.MINUTES));
+
+ // Wait for the threads to finish.
for (Thread thread : threads) {
thread.join();
}
+
+ // Allocate objects to definitely run GC before quitting.
+ try {
+ for (int i = 0; i < 1000; i++) {
+ new ArrayList<Object>(i);
+ }
+ } catch (OutOfMemoryError oom) {
+ }
+ }
+
+ private static void checkTimeout(Object o) {
+ checkTimeout(o != null);
+ }
+
+ private static void checkTimeout(boolean b) {
+ if (!b) {
+ // Something went wrong.
+ System.out.println("Bad things happened, timeout.");
+ System.exit(1);
+ }
}
private final int id;
+ private final SynchronousQueue<Boolean> waitOn;
+ private final SynchronousQueue<Boolean> pushTo;
+ private final CyclicBarrier finalBarrier;
- private Main(int id) {
+ private Main(int id, SynchronousQueue<Boolean> waitOn, SynchronousQueue<Boolean> pushTo,
+ CyclicBarrier finalBarrier) {
this.id = id;
- // Allocate this early so it's independent of how the threads are scheduled on startup.
- this.l = new ArrayList<Object>();
+ this.waitOn = waitOn;
+ this.pushTo = pushTo;
+ this.finalBarrier = finalBarrier;
}
public void run() {
- for (int i = 0; i < 1000; i++) {
- try {
- l.add(new ArrayList<Object>(i));
- } catch (OutOfMemoryError oom) {
- // Ignore.
- }
+ try {
+ work();
+ } catch (Exception exc) {
+ // Any exception is bad.
+ exc.printStackTrace(System.err);
+ System.exit(1);
}
}
- private List<Object> l;
+ public void work() throws BrokenBarrierException, InterruptedException, TimeoutException {
+ ArrayList<Object> l = new ArrayList<Object>();
+
+ // Main loop.
+ for (int i = 0; ; i++) {
+ Boolean receivedB = waitOn.poll(TIMEOUT_VALUE, TimeUnit.MINUTES);
+ checkTimeout(receivedB);
+ boolean received = receivedB;
+
+ // This is the first stage, try to allocate up till MAX_SIZE.
+ boolean oom = i >= MAX_SIZE;
+ try {
+ l.add(new ArrayList<Object>(i));
+ } catch (OutOfMemoryError oome) {
+ oom = true;
+ }
+
+ if (!received || oom) {
+ // First stage, always push false.
+ checkTimeout(pushTo.offer(Boolean.FALSE, TIMEOUT_VALUE, TimeUnit.MINUTES));
+
+ // If we received true, wait for the false to come around.
+ if (received) {
+ checkTimeout(waitOn.poll(TIMEOUT_VALUE, TimeUnit.MINUTES));
+ }
+
+ // Break out of the loop.
+ break;
+ } else {
+ // Pass on true.
+ checkTimeout(pushTo.offer(Boolean.TRUE, TIMEOUT_VALUE, TimeUnit.MINUTES));
+ }
+ }
+
+ // We have reached the final point. Wait on the barrier, but at most a minute.
+ finalBarrier.await(TIMEOUT_VALUE, TimeUnit.MINUTES);
+
+ // Done.
+ }
}