KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > EDU > oswego > cs > dl > util > concurrent > misc > SynchronizationTimer


1 /*
2   File: SynchronizationTimer.java
3
4   Originally written by Doug Lea and released into the public domain.
5   This may be used for any purposes whatsoever without acknowledgment.
6   Thanks for the assistance and support of Sun Microsystems Labs,
7   and everyone contributing, testing, and using this code.
8
9   History:
10   Date Who What
11   7Jul1998 dl Create public version
12   16Jul1998 dl fix intialization error for compute loops
13                               combined into one frame
14                               misc layout and defaults changes
15                               increase printed precision
16                               overlap get/set in Executor tests
17                               Swap defaults for swing import
18                               Active thread counts reflect executors
19   30Aug1998 dl Misc revisions to mesh with 1.1.0
20   27jan1999 dl Eliminate GC calls
21   24Nov2001 dl Increase some default values
22 */

23
24 package EDU.oswego.cs.dl.util.concurrent.misc;
25
26 // Swap the following sets of imports if necessary.
27

28 import javax.swing.*;
29 import javax.swing.border.*;
30
31 //import com.sun.java.swing.*;
32
//import com.sun.java.swing.border.*;
33

34 import EDU.oswego.cs.dl.util.concurrent.*;
35 import java.awt.*;
36 import java.awt.event.*;
37 import java.io.*;
38 import java.net.*;
39 import java.lang.reflect.*;
40
41 /**
42  *
43  * This program records times for various fine-grained synchronization
44  * schemes, and provides some ways of measuring them over different
45  * context parameters.
46  *
47  * <p>
48  * Quick start:
49  * <ol>
50  * <li>javac -d <em>base of some CLASSPATH</em> *.java <br>
51  * You'll need Swing (JFC). (This
52  * program currently imports the javax.swing versions.
53  * You can edit imports to instead use other versions.)
54  * <li>java EDU.oswego.cs.dl.util.concurrent.misc.SynchronizationTimer <br>
55  * <li> Click<em> start</em>.
56  * Clicking <em>stop</em> cancels the run. Cancellation can take
57  * a while when there are a lot of threads.
58  * <li>For more explanation about tested classes, see
59  * <a HREF="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">Documentation for util.concurrent</a>
60  * </ol>
61  *
62  * <p>
63  * Synchronization schemes are tested around implementations and
64  * subclasses of <code>RNG</code>, which is just a hacked random
65  * number generator class. Objects of this class have just enough
66  * state and require just enough computation to be reasonable minimal
67  * targets. (Additionally, random numbers are needed a lot in these
68  * kinds of time tests, so basing them on objects that produce random
69  * numbers is convenient.) Computation of each random number is
70  * padded a bit with an adjustable compute loop running a random
71  * number of times to avoid getting schedulers locked into
72  * uninteresting patterns.
73  *
74  * <p>
75  * Each iteration of each test ultimately somehow calls
76  * the random number generation
77  * method of an RNG. The time listed is the average time it took to do
78  * one iteration, in microseconds. These are just based on wallclock
79  * time (System.currentTimeMillis()). Thread
80  * construction time is <em>NOT</em> included in these times.
81  * In tests with many threads, construction and other bookkeeping
82  * can take longer than the tests themselves.
83  * <p>
84  * Results are listed in a table, and optionally printed on standard output.
85  * You can redirect standard output to save to a file.
86  * <p>
87  * The total amount of ``real'' computation reported in each cell is
88  * the same. Thus, the unobtainably ideal pattern of results would be
89  * for every cell of the table to be the same (and very small).
90  * <p>
91  * A thread pool (PooledExecutor) is used to manage the threads used in
92  * test runs. The current number of active threads is indicated in
93  * the panel. It should normally be at most three plus the number of threads used in the
94  * indicated test column (there are at most three overhead threads per run), although
95  * it may transiently climb, and is larger in those tests that
96  * generate their own internal threads (for example ThreadedExceutor). If the
97  * indicated size fails to return to zero within about 10 seconds of
98  * either hitting stop
99  * or the end of a run, you may have a
100  * problem with interruption handling on your Java VM.
101  *
102  * <p>
103  * This program cannot
104  * tell you how busy your computer is while running tests.
105  * You can run a utility program (for
106  * example <code>perfmeter</code> or <code>top</code> on unix)
107  * alongside this program
108  * to find out.
109  * <p>
110  * A number of control parameters can be changed at any time.
111  * Most combinations of parameter settings create contexts
112  * that are completely unrepresentative of those seen in practical
113  * applications. However, they can be set to provide rough analogs of
114  * real applications, and the results used as rough guesses about
115  * performance impact. Also, do not be too upset about slow
116  * performance on tests representing situations
117  * that would never occur in practice.
118  * <p>
119  *
120  * You can control parameters by clicking any of the following,
121  * at any time. (You can even change parameters
122  * while tests are running, in which case they will take
123  * effect as soon as possible. Most controls momentarily stall
124  * while test objects and threads are being constructed, to avoid
125  * inconsistencies during test runs.)
126  * <dl>
127  *
128  * <dt> Number of threads
129  *
130  * <dd> Controls concurrency. The indicated number of threads are
131  * started simultaneously and then waited out.
132  *
133  * <dt>Contention.
134  *
135  * <dd>Percent sharing among threads. Zero percent means that each
136  * thread has its own RNG object, so there is no
137  * interference among threads. The zero
138  * percent case thus shows the cost of synchronization mechanics that
139  * happen to never be needed.
140  * 100 percent sharing means that all
141  * threads call methods on the same object, so each thread will have to
142  * wait until the RNG objects are not being used by others.
143  * In between is in between: Only the given percentage of calls are
144  * made to shared RNG objects; others are to unshared.
145  * Contention in classes that use Channels works slightly differently:
146  * The Channels are shared, not the base RNG objects. (Another way
147  * of looking at it is that tests demonstrate effects of multiple
148  * producers and consumers on the same channel.)
149  *
150  * <dt>Classes
151  * <dd>You can choose to only test the indicated classes. You can
152  * probably figure out how to add more classes to run yourself.
153  *
154  * <dt>Calls per thread per test
155  *
156  * <dd>Specifies number of iterations per thread per test. The listed
157  * times are averages over these iterations. The default seems to
158  * provide precise enough values for informal testing purposes.
159  * You should expect to see a fair amount of variation across
160  * repeated runs.
161  * If you get zeroes printed in any cell, this means that the
162  * test ran too fast to measure in milleconds, so you should increase the
163  * iterations value.
164  *
165  * <dt> Computations per call
166  *
167  * <dd>Specifies length of each call by setting an internal looping
168  * parameter inside each RNG object. Shorter calls lead to shorter
169  * times between synchronization measures. Longer calls, along with
170  * high contention can be used to force timeouts to occur.
171  *
172  * <dt> Iterations per barrier.
173  *
174  * <dd> Specifies the number of iterations performed by each thread until
175  * a synchronization barrier is forced with other threads, forcing
176  * it to wait for other threads to reach the same number of iterations. This
177  * controls the amount of interaction (versus contention) among threads.
178  * Setting to a value greater than the number of iterations per test
179  * effectively disables barriers.
180  *
181  * <dt> Threads per barrier
182  *
183  * <dd> Specifies how many threads are forced to synchronize at each
184  * barrier point. Greater numbers cause more threads to wait for each
185  * other at barriers. Setting to 1 means that a thread only has to
186  * wait for itself, which means not to wait at all.
187  *
188  * <dt>Lock mode
189  *
190  * <dd>For classes that support it, this controls whether mutual
191  * exclusion waits are done via standard blocking synchronization, or
192  * a loop repeatedly calling a timed wait.
193  *
194  * <dt>Producer mode
195  *
196  * <dd>For classes that support it, this controls whether producers
197  * perform blocking puts versus loops repeatedly calling offer.
198  *
199  * <dt>Consumer mode
200  *
201  * <dd>For classes that support it, this controls whether consumers
202  * perform blocking takes versus loops repeatedly calling poll.
203  *
204  * <dt> Timeouts
205  *
206  * <dd> Specifies the duration of timeouts used in timeout mode. A
207  * value of zero results in pure spin-loops.
208  *
209  * <dt>Producer/consumer rates.
210  *
211  * <dd>For tests involving producer/consumer pairs, this controls
212  * whether the producer is much faster, about the same speed, or much
213  * slower than the consumer. This is implemented by having the
214  * producer do all, half, or none of the actual calls to update, in
215  * addition to adding elements to channel.
216  *
217  * <dt>Buffer capacity
218  *
219  * <dd>For tests involving finite capacity
220  * buffers, this controls maximum buffer size.
221  *
222  * </dl>
223  *
224  * <p>
225  * To scaffold all this, the RNG class is defined in
226  * layers. Each RNG has internal non-public methods that do the actual
227  * computation, and public methods that call the internal ones. The
228  * particular classes run in tests might change over time, but
229  * currently includes the following general kinds:
230  *
231  * <dl>
232  *
233  *
234  * <dt> Using built-in synchronization
235  * <dd> Versions of RNG classes that use (or don't use)
236  * synchronized methods and/or blocks. Also some tests of
237  * simple SynchronizedVariables. Tests that would not
238  * be thread-safe are not run when there is more than one
239  * thread and non-zero contention.
240  *
241  *
242  * <dt> Using <code>Sync</code> classes as locks
243  * <dd> Classes protecting public methods via Semaphores, mutexes, etc.
244  * In each case, the outer public methods delegate actions to
245  * another RNG object, surrounded by acquire/release/etc. The
246  * class called SDelegated does this using builtin
247  * synchronization rather than Sync locks
248  * so might be a useful comparison.
249  *
250  * <dt> Using Channels
251  * <dd> These classes work a little bit differently than the others.
252  * Each test arranges that half of the threads behave as producers,
253  * and half as consumers. Each test iteration puts/takes an RNG object
254  * through a channel before or after executing its update
255  * method. When the number of threads is one, each producer
256  * simply consumers its own object. Some Channels (notably
257  * SynchronousChannels) cannot be used with only one thread,
258  * in which case the test is skipped.
259  *
260  * <dt> Using Executors
261  * <dd> These classes arrange for each RNG update to occur
262  * as an executable command. Each test iteration passes a
263  * command to an Executor, which eventually executes it.
264  * Execution is overlapped: Each iteration starts a new
265  * command, and then waits for the previous command to complete.
266  *
267  * </dl>
268  *
269  * <p>
270  *
271  * The test code is ugly; it has just evolved over the years. Sorry.
272 **/

273
274 public class SynchronizationTimer {
275
276   /** Start up this application **/
277   public static void main(String JavaDoc[] args) {
278
279     JFrame frame = new JFrame("Times per call in microseconds");
280
281     frame.addWindowListener(new WindowAdapter() {
282       public void windowClosing(WindowEvent e) {System.exit(0);}
283     });
284   
285     frame.getContentPane().add(new SynchronizationTimer().mainPanel());
286     frame.pack();
287     frame.setVisible(true);
288   }
289
290   /**
291    * Information about classes to be tested
292    **/

293   static class TestedClass {
294     final String JavaDoc name;
295     final Class JavaDoc cls;
296     final boolean multipleOK;
297     final boolean singleOK;
298     final Class JavaDoc buffCls;
299     Boolean JavaDoc enabled_ = new Boolean JavaDoc(true);
300
301     synchronized void setEnabled(Boolean JavaDoc b) { enabled_ = b; }
302     synchronized Boolean JavaDoc getEnabled() { return enabled_; }
303
304     synchronized void toggleEnabled() {
305       boolean enabled = enabled_.booleanValue();
306       enabled_ = new Boolean JavaDoc(!enabled);
307     }
308     
309     synchronized boolean isEnabled(int nthreads, Fraction shared) {
310       boolean enabled = enabled_.booleanValue();
311       if (!enabled) return false;
312       if (!singleOK && nthreads <= 1) return false;
313       if (!multipleOK && nthreads > 1 && shared.compareTo(0) > 0) return false;
314       return true;
315     }
316     
317     
318     TestedClass(String JavaDoc n, Class JavaDoc c, boolean m, boolean sok) {
319       name = n; cls = c; multipleOK = m; singleOK = sok;
320       buffCls = null;
321     }
322     
323     TestedClass(String JavaDoc n, Class JavaDoc c, boolean m, boolean sok, Class JavaDoc bc) {
324       name = n; cls = c; multipleOK = m; singleOK = sok;
325       buffCls = bc;
326     }
327     
328     static final TestedClass dummy =
329       new TestedClass("", null, false, false);
330
331     static final TestedClass[] classes = {
332       
333       new TestedClass("NoSynchronization", NoSynchRNG.class, false, true),
334       new TestedClass("PublicSynchronization", PublicSynchRNG.class, true, true),
335       new TestedClass("NestedSynchronization", AllSynchRNG.class, true, true),
336       
337       new TestedClass("SDelegated", SDelegatedRNG.class, true, true),
338       
339       new TestedClass("SynchLongUsingSet", SynchLongRNG.class, true, true),
340       new TestedClass("SynchLongUsingCommit", AClongRNG.class, true, true),
341       
342       new TestedClass("Semaphore", SemRNG.class, true, true),
343       new TestedClass("WaiterPrefSemaphore", WpSemRNG.class, true, true),
344       new TestedClass("FIFOSemaphore", FifoRNG.class, true, true),
345       new TestedClass("PrioritySemaphore", PrioritySemRNG.class, true, true),
346       new TestedClass("Mutex", MutexRNG.class, true, true),
347       new TestedClass("ReentrantLock", RlockRNG.class, true, true),
348       
349       new TestedClass("WriterPrefRWLock", WpRWlockRNG.class, true, true),
350       new TestedClass("ReaderPrefRWLock", ReaderPrefRWlockRNG.class, true, true),
351       new TestedClass("FIFORWLock", FIFORWlockRNG.class, true, true),
352       new TestedClass("ReentrantRWL", ReentrantRWlockRNG.class, true, true),
353       
354       
355       
356       new TestedClass("LinkedQueue", ChanRNG.class, true, true,
357                       LinkedQueue.class),
358
359       new TestedClass("WaitFreeQueue", ChanRNG.class, true, true,
360                       WaitFreeQueue.class),
361
362       new TestedClass("BoundedLinkedQueue", ChanRNG.class, true, true,
363                       BoundedLinkedQueue.class),
364       new TestedClass("BoundedBuffer", ChanRNG.class, true, true,
365                       BoundedBuffer.class),
366       new TestedClass("CondVarBoundedBuffer", ChanRNG.class, true, true,
367                       CVBuffer.class),
368       new TestedClass("BoundedPriorityQueue", ChanRNG.class, true, true,
369                       BoundedPriorityQueue.class),
370       new TestedClass("Slot", ChanRNG.class, true, true,
371                       Slot.class),
372       // new TestedClass("FIFOSlot", ChanRNG.class, true, true, FIFOSlot.class),
373
new TestedClass("SynchronousChannel", ChanRNG.class, true, false,
374                       SynchronousChannel.class),
375
376       
377       new TestedClass("DirectExecutor", DirectExecutorRNG.class, true, true),
378       new TestedClass("SemaphoreLckExecutor", LockedSemRNG.class, true, true),
379       new TestedClass("QueuedExecutor", QueuedExecutorRNG.class, true, true),
380       new TestedClass("ThreadedExecutor", ThreadedExecutorRNG.class, true, true),
381       new TestedClass("PooledExecutor", PooledExecutorRNG.class, true, true),
382       
383       // new TestedClass("Pipe", ChanRNG.class, true, true, PipedChannel.class),
384
};
385   }
386
387
388
389   // test parameters
390

391   static final int[] nthreadsChoices = {
392     1,
393     2,
394     4,
395     8,
396     16,
397     32,
398     64,
399     128,
400     256,
401     512,
402     1024
403   };
404
405   static final int BLOCK_MODE = 0;
406   static final int TIMEOUT_MODE = 1;
407
408   static final int[] syncModes = { BLOCK_MODE, TIMEOUT_MODE, };
409
410   // misc formatting utilities
411

412   static String JavaDoc modeToString(int m) {
413     String JavaDoc sms;
414     if (m == BLOCK_MODE) sms = "block";
415     else if (m == TIMEOUT_MODE) sms = "timeout";
416     else sms = "No such mode";
417     return sms;
418   }
419
420   static String JavaDoc biasToString(int b) {
421     String JavaDoc sms;
422     if (b < 0) sms = "slower producer";
423     else if (b == 0) sms = "balanced prod/cons rate";
424     else if (b > 0) sms = "slower consumer";
425     else sms = "No such bias";
426     return sms;
427   }
428
429
430   static String JavaDoc p2ToString(int n) { // print power of two
431
String JavaDoc suf = "";
432     if (n >= 1024) {
433       n = n / 1024;
434       suf = "K";
435       if (n >= 1024) {
436         n = n / 1024;
437         suf = "M";
438       }
439     }
440     return n + suf;
441   }
442
443   static final int PRECISION = 10; // microseconds
444

445   static String JavaDoc formatTime(long ns, boolean showDecimal) {
446     long intpart = ns / PRECISION;
447     long decpart = ns % PRECISION;
448     if (!showDecimal) {
449       if (decpart >= PRECISION/2)
450         ++intpart;
451       return Long.toString(intpart);
452     }
453     else {
454       String JavaDoc sint = Long.toString(intpart);
455       String JavaDoc sdec = Long.toString(decpart);
456       if (decpart == 0) {
457         int z = PRECISION;
458         while (z > 10) {
459           sdec = "0" + sdec;
460           z /= 10;
461         }
462       }
463       String JavaDoc ts = sint + "." + sdec;
464       return ts;
465     }
466   }
467     
468   static class ThreadInfo {
469     final String JavaDoc name;
470     final int number;
471     Boolean JavaDoc enabled;
472     ThreadInfo(int nthr) {
473       number = nthr;
474       name = p2ToString(nthr);
475       enabled = new Boolean JavaDoc(true);
476     }
477
478     synchronized Boolean JavaDoc getEnabled() { return enabled; }
479     synchronized void setEnabled(Boolean JavaDoc v) { enabled = v; }
480     synchronized void toggleEnabled() {
481       enabled = new Boolean JavaDoc(!enabled.booleanValue());
482     }
483   }
484
485   final ThreadInfo[] threadInfo = new ThreadInfo[nthreadsChoices.length];
486
487   boolean threadEnabled(int nthreads) {
488     return threadInfo[nthreads].getEnabled().booleanValue();
489   }
490
491   // This used to be a JTable datamodel, but now just part of this class ...
492

493   final static int headerRows = 1;
494   final static int classColumn = 0;
495   final static int headerColumns = 1;
496   final int tableRows = TestedClass.classes.length + headerRows;
497   final int tableColumns = nthreadsChoices.length + headerColumns;
498   
499   final JComponent[][] resultTable_ = new JComponent[tableRows][tableColumns];
500   
501   JPanel resultPanel() {
502
503     JPanel[] colPanel = new JPanel[tableColumns];
504     for (int col = 0; col < tableColumns; ++col) {
505       colPanel[col] = new JPanel();
506       colPanel[col].setLayout(new GridLayout(tableRows, 1));
507       if (col != 0)
508         colPanel[col].setBackground(Color.white);
509     }
510
511     Color hdrbg = colPanel[0].getBackground();
512     Border border = new LineBorder(hdrbg);
513
514     Font font = new Font("Dialog", Font.PLAIN, 12);
515     Dimension labDim = new Dimension(40, 16);
516     Dimension cbDim = new Dimension(154, 16);
517
518     JLabel cornerLab = new JLabel(" Classes \\ Threads");
519     cornerLab.setMinimumSize(cbDim);
520     cornerLab.setPreferredSize(cbDim);
521     cornerLab.setFont(font);
522     resultTable_[0][0] = cornerLab;
523     colPanel[0].add(cornerLab);
524     
525     for (int col = 1; col < tableColumns; ++col) {
526       final int nthreads = col - headerColumns;
527       JCheckBox tcb = new JCheckBox(threadInfo[nthreads].name, true);
528       tcb.addActionListener(new ActionListener() {
529         public void actionPerformed(ActionEvent evt) {
530           threadInfo[nthreads].toggleEnabled();
531         }});
532       
533       
534       tcb.setMinimumSize(labDim);
535       tcb.setPreferredSize(labDim);
536       tcb.setFont(font);
537       tcb.setBackground(hdrbg);
538       resultTable_[0][col] = tcb;
539       colPanel[col].add(tcb);
540     }
541     
542     
543     for (int row = 1; row < tableRows; ++row) {
544       final int cls = row - headerRows;
545       
546       JCheckBox cb = new JCheckBox(TestedClass.classes[cls].name, true);
547       cb.addActionListener(new ActionListener() {
548         public void actionPerformed(ActionEvent evt) {
549           TestedClass.classes[cls].toggleEnabled();
550         }});
551       
552       resultTable_[row][0] = cb;
553       cb.setMinimumSize(cbDim);
554       cb.setPreferredSize(cbDim);
555       cb.setFont(font);
556       colPanel[0].add(cb);
557       
558       for (int col = 1; col < tableColumns; ++col) {
559         int nthreads = col - headerColumns;
560         JLabel lab = new JLabel("");
561         resultTable_[row][col] = lab;
562         
563         lab.setMinimumSize(labDim);
564         lab.setPreferredSize(labDim);
565         lab.setBorder(border);
566         lab.setFont(font);
567         lab.setBackground(Color.white);
568         lab.setForeground(Color.black);
569         lab.setHorizontalAlignment(JLabel.RIGHT);
570         
571         colPanel[col].add(lab);
572       }
573     }
574     
575     JPanel tblPanel = new JPanel();
576     tblPanel.setLayout(new BoxLayout(tblPanel, BoxLayout.X_AXIS));
577     for (int col = 0; col < tableColumns; ++col) {
578       tblPanel.add(colPanel[col]);
579     }
580     
581     return tblPanel;
582     
583   }
584
585   void setTime(final long ns, int clsIdx, int nthrIdx) {
586     int row = clsIdx+headerRows;
587     int col = nthrIdx+headerColumns;
588     final JLabel cell = (JLabel)(resultTable_[row][col]);
589
590     SwingUtilities.invokeLater(new Runnable JavaDoc() {
591       public void run() {
592         cell.setText(formatTime(ns, true));
593       }
594     });
595   }
596   
597      
598
599   void clearTable() {
600     for (int i = 1; i < tableRows; ++i) {
601       for (int j = 1; j < tableColumns; ++j) {
602         ((JLabel)(resultTable_[i][j])).setText("");
603       }
604     }
605   }
606
607   void setChecks(final boolean setting) {
608     for (int i = 0; i < TestedClass.classes.length; ++i) {
609       TestedClass.classes[i].setEnabled(new Boolean JavaDoc(setting));
610       ((JCheckBox)resultTable_[i+1][0]).setSelected(setting);
611     }
612   }
613
614
615   public SynchronizationTimer() {
616     for (int i = 0; i < threadInfo.length; ++i)
617       threadInfo[i] = new ThreadInfo(nthreadsChoices[i]);
618
619   }
620   
621   final SynchronizedInt nextClassIdx_ = new SynchronizedInt(0);
622   final SynchronizedInt nextThreadIdx_ = new SynchronizedInt(0);
623
624
625   JPanel mainPanel() {
626     new PrintStart(); // classloader bug workaround
627
JPanel paramPanel = new JPanel();
628     paramPanel.setLayout(new GridLayout(5, 3));
629
630     JPanel buttonPanel = new JPanel();
631     buttonPanel.setLayout(new GridLayout(1, 3));
632     
633     startstop_.addActionListener(new ActionListener() {
634       public void actionPerformed(ActionEvent evt) {
635         if (running_.get())
636           cancel();
637         else {
638           try {
639             startTestSeries(new TestSeries());
640           }
641           catch (InterruptedException JavaDoc ex) {
642             endTestSeries();
643           }
644         }
645       }});
646     
647     paramPanel.add(startstop_);
648     
649     JPanel p1 = new JPanel();
650     p1.setLayout(new GridLayout(1, 2));
651     
652     JButton continueButton = new JButton("Continue");
653
654     continueButton.addActionListener(new ActionListener() {
655       public void actionPerformed(ActionEvent evt) {
656         if (!running_.get()) {
657           try {
658             startTestSeries(new TestSeries(nextClassIdx_.get(),
659                                            nextThreadIdx_.get()));
660           }
661           catch (InterruptedException JavaDoc ex) {
662             endTestSeries();
663           }
664         }
665       }});
666
667     p1.add(continueButton);
668
669     JButton clearButton = new JButton("Clear cells");
670     
671     clearButton.addActionListener(new ActionListener(){
672       public void actionPerformed(ActionEvent evt) {
673         clearTable();
674       }
675     });
676
677     p1.add(clearButton);
678
679     paramPanel.add(p1);
680
681     JPanel p3 = new JPanel();
682     p3.setLayout(new GridLayout(1, 2));
683     
684     JButton setButton = new JButton("All classes");
685     
686     setButton.addActionListener(new ActionListener(){
687       public void actionPerformed(ActionEvent evt) {
688         setChecks(true);
689       }
690     });
691
692     p3.add(setButton);
693
694
695     JButton unsetButton = new JButton("No classes");
696     
697     unsetButton.addActionListener(new ActionListener(){
698       public void actionPerformed(ActionEvent evt) {
699         setChecks(false);
700       }
701     });
702
703     p3.add(unsetButton);
704     paramPanel.add(p3);
705
706     JPanel p2 = new JPanel();
707     // p2.setLayout(new GridLayout(1, 2));
708
p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
709
710
711     JCheckBox consoleBox = new JCheckBox("Console echo");
712     consoleBox.addItemListener(new ItemListener() {
713       public void itemStateChanged(ItemEvent evt) {
714         echoToSystemOut.complement();
715       }
716     });
717
718     
719
720     JLabel poolinfo = new JLabel("Active threads: 0");
721
722     p2.add(poolinfo);
723     p2.add(consoleBox);
724
725     paramPanel.add(p2);
726
727     paramPanel.add(contentionBox());
728     paramPanel.add(itersBox());
729     paramPanel.add(cloopBox());
730     paramPanel.add(barrierBox());
731     paramPanel.add(exchangeBox());
732     paramPanel.add(biasBox());
733     paramPanel.add(capacityBox());
734     paramPanel.add(timeoutBox());
735     paramPanel.add(syncModePanel());
736     paramPanel.add(producerSyncModePanel());
737     paramPanel.add(consumerSyncModePanel());
738
739     startPoolStatus(poolinfo);
740
741     JPanel mainPanel = new JPanel();
742     mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
743
744     JPanel tblPanel = resultPanel();
745
746     mainPanel.add(tblPanel);
747     mainPanel.add(paramPanel);
748     return mainPanel;
749   }
750
751   
752   
753   
754   JComboBox syncModePanel() {
755     JComboBox syncModeComboBox = new JComboBox();
756     
757     for (int j = 0; j < syncModes.length; ++j) {
758       String JavaDoc lab = "Locks: " + modeToString(syncModes[j]);
759       syncModeComboBox.addItem(lab);
760     }
761     syncModeComboBox.addItemListener(new ItemListener() {
762       public void itemStateChanged(ItemEvent evt) {
763         JComboBox src = (JComboBox)(evt.getItemSelectable());
764         int idx = src.getSelectedIndex();
765         RNG.syncMode.set(syncModes[idx]);
766       }
767     });
768     
769     RNG.syncMode.set(syncModes[0]);
770     syncModeComboBox.setSelectedIndex(0);
771     return syncModeComboBox;
772   }
773
774   JComboBox producerSyncModePanel() {
775     JComboBox producerSyncModeComboBox = new JComboBox();
776     
777     for (int j = 0; j < syncModes.length; ++j) {
778       String JavaDoc lab = "Producers: " + modeToString(syncModes[j]);
779       producerSyncModeComboBox.addItem(lab);
780     }
781     producerSyncModeComboBox.addItemListener(new ItemListener() {
782       public void itemStateChanged(ItemEvent evt) {
783         JComboBox src = (JComboBox)(evt.getItemSelectable());
784         int idx = src.getSelectedIndex();
785         RNG.producerMode.set(syncModes[idx]);
786       }
787     });
788     
789     RNG.producerMode.set(syncModes[0]);
790     producerSyncModeComboBox.setSelectedIndex(0);
791     return producerSyncModeComboBox;
792   }
793
794   JComboBox consumerSyncModePanel() {
795     JComboBox consumerSyncModeComboBox = new JComboBox();
796     
797     for (int j = 0; j < syncModes.length; ++j) {
798       String JavaDoc lab = "Consumers: " + modeToString(syncModes[j]);
799       consumerSyncModeComboBox.addItem(lab);
800     }
801     consumerSyncModeComboBox.addItemListener(new ItemListener() {
802       public void itemStateChanged(ItemEvent evt) {
803         JComboBox src = (JComboBox)(evt.getItemSelectable());
804         int idx = src.getSelectedIndex();
805         RNG.consumerMode.set(syncModes[idx]);
806       }
807     });
808     
809     RNG.consumerMode.set(syncModes[0]);
810     consumerSyncModeComboBox.setSelectedIndex(0);
811     return consumerSyncModeComboBox;
812   }
813
814
815   
816   JComboBox contentionBox() {
817     final Fraction[] contentionChoices = {
818       new Fraction(0, 1),
819       new Fraction(1, 16),
820       new Fraction(1, 8),
821       new Fraction(1, 4),
822       new Fraction(1, 2),
823       new Fraction(1, 1)
824     };
825     
826     JComboBox contentionComboBox = new JComboBox();
827     
828     for (int j = 0; j < contentionChoices.length; ++j) {
829       String JavaDoc lab = contentionChoices[j].asDouble() * 100.0 +
830         "% contention/sharing";
831       contentionComboBox.addItem(lab);
832     }
833     contentionComboBox.addItemListener(new ItemListener() {
834       public void itemStateChanged(ItemEvent evt) {
835         JComboBox src = (JComboBox)(evt.getItemSelectable());
836         int idx = src.getSelectedIndex();
837         contention_.set(contentionChoices[idx]);
838       }
839     });
840     
841     contention_.set(contentionChoices[3]);
842     contentionComboBox.setSelectedIndex(3);
843     return contentionComboBox;
844   }
845   
846   JComboBox itersBox() {
847     final int[] loopsPerTestChoices = {
848       1,
849       16,
850       256,
851       1024,
852       2 * 1024,
853       4 * 1024,
854       8 * 1024,
855       16 * 1024,
856       32 * 1024,
857       64 * 1024,
858       128 * 1024,
859       256 * 1024,
860       512 * 1024,
861       1024 * 1024,
862     };
863     
864     JComboBox precComboBox = new JComboBox();
865     
866     for (int j = 0; j < loopsPerTestChoices.length; ++j) {
867       String JavaDoc lab = p2ToString(loopsPerTestChoices[j]) +
868         " calls per thread per test";
869       precComboBox.addItem(lab);
870     }
871     precComboBox.addItemListener(new ItemListener() {
872       public void itemStateChanged(ItemEvent evt) {
873         JComboBox src = (JComboBox)(evt.getItemSelectable());
874         int idx = src.getSelectedIndex();
875         loopsPerTest_.set(loopsPerTestChoices[idx]);
876       }
877     });
878     
879     loopsPerTest_.set(loopsPerTestChoices[8]);
880     precComboBox.setSelectedIndex(8);
881
882     return precComboBox;
883   }
884   
885   JComboBox cloopBox() {
886     final int[] computationsPerCallChoices = {
887       1,
888       2,
889       4,
890       8,
891       16,
892       32,
893       64,
894       128,
895       256,
896       512,
897       1024,
898       2 * 1024,
899       4 * 1024,
900       8 * 1024,
901       16 * 1024,
902       32 * 1024,
903       64 * 1024,
904     };
905     
906     JComboBox cloopComboBox = new JComboBox();
907     
908     for (int j = 0; j < computationsPerCallChoices.length; ++j) {
909       String JavaDoc lab = p2ToString(computationsPerCallChoices[j]) +
910         " computations per call";
911       cloopComboBox.addItem(lab);
912     }
913     cloopComboBox.addItemListener(new ItemListener() {
914       public void itemStateChanged(ItemEvent evt) {
915         JComboBox src = (JComboBox)(evt.getItemSelectable());
916         int idx = src.getSelectedIndex();
917         RNG.computeLoops.set(computationsPerCallChoices[idx]);
918       }
919     });
920     
921     RNG.computeLoops.set(computationsPerCallChoices[3]);
922     cloopComboBox.setSelectedIndex(3);
923     return cloopComboBox;
924   }
925   
926   JComboBox barrierBox() {
927     final int[] itersPerBarrierChoices = {
928       1,
929       2,
930       4,
931       8,
932       16,
933       32,
934       64,
935       128,
936       256,
937       512,
938       1024,
939       2 * 1024,
940       4 * 1024,
941       8 * 1024,
942       16 * 1024,
943       32 * 1024,
944       64 * 1024,
945       128 * 1024,
946       256 * 1024,
947       512 * 1024,
948       1024 * 1024,
949     };
950     
951     JComboBox barrierComboBox = new JComboBox();
952     
953     for (int j = 0; j < itersPerBarrierChoices.length; ++j) {
954       String JavaDoc lab = p2ToString(itersPerBarrierChoices[j]) +
955         " iterations per barrier";
956       barrierComboBox.addItem(lab);
957     }
958     barrierComboBox.addItemListener(new ItemListener() {
959       public void itemStateChanged(ItemEvent evt) {
960         JComboBox src = (JComboBox)(evt.getItemSelectable());
961         int idx = src.getSelectedIndex();
962         RNG.itersPerBarrier.set(itersPerBarrierChoices[idx]);
963       }
964     });
965     
966     RNG.itersPerBarrier.set(itersPerBarrierChoices[13]);
967     barrierComboBox.setSelectedIndex(13);
968
969     // RNG.itersPerBarrier.set(itersPerBarrierChoices[15]);
970
// barrierComboBox.setSelectedIndex(15);
971

972     return barrierComboBox;
973   }
974   
975   JComboBox exchangeBox() {
976     final int[] exchangerChoices = {
977       1,
978       2,
979       4,
980       8,
981       16,
982       32,
983       64,
984       128,
985       256,
986       512,
987       1024,
988     };
989     
990     JComboBox exchComboBox = new JComboBox();
991     
992     for (int j = 0; j < exchangerChoices.length; ++j) {
993       String JavaDoc lab = p2ToString(exchangerChoices[j]) +
994         " max threads per barrier";
995       exchComboBox.addItem(lab);
996     }
997     exchComboBox.addItemListener(new ItemListener() {
998       public void itemStateChanged(ItemEvent evt) {
999         JComboBox src = (JComboBox)(evt.getItemSelectable());
1000        int idx = src.getSelectedIndex();
1001        RNG.exchangeParties.set(exchangerChoices[idx]);
1002      }
1003    });
1004    
1005    RNG.exchangeParties.set(exchangerChoices[1]);
1006    exchComboBox.setSelectedIndex(1);
1007</