public class Benchmarks extends TestCase {
public void testAccessLogGetDate() throws Exception {
// Is it better to use a sync or a thread local here?
- BenchmarkTest getDate = new GetDateBenchmarkTest();
- getDate.doTest(5);
+ BenchmarkTest benchmark = new BenchmarkTest();
+ Runnable[] tests = new Runnable[] { new GetDateBenchmarkTest_Sync(),
+ new GetDateBenchmarkTest_Local() };
+ benchmark.doTest(5, tests);
}
- private static class GetDateBenchmarkTest extends BenchmarkTest {
+ private static class GetDateBenchmarkTest_Sync implements Runnable {
+
+ public String toString() {
+ return "Syncs";
+ }
+
private volatile long currentMillis = 0;
private volatile Date currentDate = null;
- private ThreadLocal<Long> currentMillisLocal = new ThreadLocal<Long>() {
- protected Long initialValue() {
- return Long.valueOf(0);
- }
- };
-
- private ThreadLocal<Date> currentDateLocal = new ThreadLocal<Date>();
+ public void run() {
+ getCurrentDate();
+ }
- public Object doSync() {
+ public Date getCurrentDate() {
long systime = System.currentTimeMillis();
if ((systime - currentMillis) > 1000) {
synchronized (this) {
}
}
}
- return currentDate;
+ return currentDate;
+ }
+ }
+
+ private static class GetDateBenchmarkTest_Local implements Runnable {
+
+ public String toString() {
+ return "ThreadLocals";
+ }
+
+ private ThreadLocal<Long> currentMillisLocal = new ThreadLocal<Long>() {
+ protected Long initialValue() {
+ return Long.valueOf(0);
+ }
+ };
+
+ private ThreadLocal<Date> currentDateLocal = new ThreadLocal<Date>();
+
+ public void run() {
+ getCurrentDate();
}
-
- public Object doLocal() {
+
+ public Date getCurrentDate() {
long systime = System.currentTimeMillis();
if ((systime - currentMillisLocal.get().longValue()) > 1000) {
currentDateLocal.set(new Date(systime));
currentMillisLocal.set(Long.valueOf(systime));
}
- return currentDateLocal.get();
+ return currentDateLocal.get();
}
}
-
public void testAccessLogTimeDateElement() throws Exception {
// Is it better to use a sync or a thread local here?
- BenchmarkTest timeDateElement = new TimeDateElementBenchmarkTest();
- timeDateElement.doTest(5);
+ BenchmarkTest benchmark = new BenchmarkTest();
+ Runnable[] tests = new Runnable[] {
+ new TimeDateElementBenchmarkTest_Sync(),
+ new TimeDateElementBenchmarkTest_Local() };
+ benchmark.doTest(5, tests);
}
- private static class TimeDateElementBenchmarkTest extends BenchmarkTest {
+ private static abstract class TimeDateElementBenchmarkTestBase {
+ protected static final String months[] = { "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ protected String lookup(String month) {
+ int index;
+ try {
+ index = Integer.parseInt(month) - 1;
+ } catch (Throwable t) {
+ index = 0; // Can not happen, in theory
+ }
+ return (months[index]);
+ }
+ }
+
+ private static class TimeDateElementBenchmarkTest_Sync extends
+ TimeDateElementBenchmarkTestBase implements Runnable {
+
+ public String toString() {
+ return "Syncs";
+ }
+
private volatile long currentMillis = 0;
private volatile Date currentDate = null;
private String currentDateString = null;
private SimpleDateFormat dayFormatter = new SimpleDateFormat("dd");
private SimpleDateFormat monthFormatter = new SimpleDateFormat("MM");
private SimpleDateFormat yearFormatter = new SimpleDateFormat("yyyy");
- private SimpleDateFormat timeFormatter = new SimpleDateFormat("hh:mm:ss");
-
- private ThreadLocal<Long> currentMillisLocal = new ThreadLocal<Long>() {
- protected Long initialValue() {
- return Long.valueOf(0);
- }
- };
- private ThreadLocal<Date> currentDateLocal = new ThreadLocal<Date>();
- private ThreadLocal<SimpleDateFormat> dayFormatterLocal =
- new ThreadLocal<SimpleDateFormat>() {
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("dd");
- }
- };
- private ThreadLocal<SimpleDateFormat> monthFormatterLocal =
- new ThreadLocal<SimpleDateFormat>() {
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("MM");
- }
- };
- private ThreadLocal<SimpleDateFormat> yearFormatterLocal =
- new ThreadLocal<SimpleDateFormat>() {
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("yyyy");
- }
- };
- private ThreadLocal<SimpleDateFormat> timeFormatterLocal =
- new ThreadLocal<SimpleDateFormat>() {
- protected SimpleDateFormat initialValue() {
- return new SimpleDateFormat("hh:mm:ss");
- }
- };
-
- public Object doSync() {
+ private SimpleDateFormat timeFormatter = new SimpleDateFormat(
+ "hh:mm:ss");
+
+ public void run() {
+ printDate();
+ }
+
+ public StringBuffer printDate() {
StringBuffer buf = new StringBuffer();
Date date = getDateSync();
if (currentDate != date) {
buf.append(currentDateString);
return buf;
}
-
- protected static final String months[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- private String lookup(String month) {
- int index;
- try {
- index = Integer.parseInt(month) - 1;
- } catch (Throwable t) {
- index = 0; // Can not happen, in theory
- }
- return (months[index]);
- }
-
private Date getDateSync() {
long systime = System.currentTimeMillis();
if ((systime - currentMillis) > 1000) {
}
}
}
- return currentDate;
+ return currentDate;
+ }
+ }
+
+ private static class TimeDateElementBenchmarkTest_Local extends
+ TimeDateElementBenchmarkTestBase implements Runnable {
+
+ public String toString() {
+ return "ThreadLocals";
+ }
+
+ private volatile Date currentDate = null;
+ private String currentDateString = null;
+
+ private ThreadLocal<Long> currentMillisLocal = new ThreadLocal<Long>() {
+ protected Long initialValue() {
+ return Long.valueOf(0);
+ }
+ };
+ private ThreadLocal<Date> currentDateLocal = new ThreadLocal<Date>();
+ private ThreadLocal<SimpleDateFormat> dayFormatterLocal = new ThreadLocal<SimpleDateFormat>() {
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("dd");
+ }
+ };
+ private ThreadLocal<SimpleDateFormat> monthFormatterLocal = new ThreadLocal<SimpleDateFormat>() {
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("MM");
+ }
+ };
+ private ThreadLocal<SimpleDateFormat> yearFormatterLocal = new ThreadLocal<SimpleDateFormat>() {
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("yyyy");
+ }
+ };
+ private ThreadLocal<SimpleDateFormat> timeFormatterLocal = new ThreadLocal<SimpleDateFormat>() {
+ protected SimpleDateFormat initialValue() {
+ return new SimpleDateFormat("hh:mm:ss");
+ }
+ };
+
+ public void run() {
+ printDate();
}
-
- public Object doLocal() {
+
+ public StringBuffer printDate() {
StringBuffer buf = new StringBuffer();
Date date = getDateLocal();
if (currentDate != date) {
buf.append(currentDateString);
return buf;
}
-
+
private Date getDateLocal() {
long systime = System.currentTimeMillis();
if ((systime - currentMillisLocal.get().longValue()) > 1000) {
currentDateLocal.set(new Date(systime));
currentMillisLocal.set(Long.valueOf(systime));
}
- return currentDateLocal.get();
+ return currentDateLocal.get();
}
}
-
- private static abstract class BenchmarkTest {
- public abstract Object doSync();
- public abstract Object doLocal();
-
- public void doTest(int threadCount) throws Exception {
- for (int iterations = 1000000; iterations < 10000001; iterations+=1000000) {
- doTestInternal(threadCount, iterations, true);
- doTestInternal(threadCount, iterations, false);
+ private static class BenchmarkTest {
+ public void doTest(int threadCount, Runnable[] tests) throws Exception {
+ for (int iterations = 1000000; iterations < 10000001; iterations += 1000000) {
+ for (int i = 0; i < tests.length; i++) {
+ doTestInternal(threadCount, iterations, tests[i]);
+ }
}
}
-
+
private void doTestInternal(int threadCount, int iterations,
- boolean useSyncs) throws Exception {
+ Runnable test) throws Exception {
long start = System.currentTimeMillis();
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
- threads[i] = new Thread(new TestThread(iterations, useSyncs, this));
+ threads[i] = new Thread(new TestThread(iterations, test));
}
for (int i = 0; i < threadCount; i++) {
threads[i].start();
threads[i].join();
}
long end = System.currentTimeMillis();
-
- System.out.println(this.getClass().getName() + ": " + threadCount +
- " threads and " + iterations + " iterations " +
- (useSyncs?"using Syncs":"using ThreadLocals") +
- " took " + (end-start) + "ms");
- }
+ System.out.println(test.getClass().getName() + ": " + threadCount
+ + " threads and " + iterations + " iterations using "
+ + test + " took " + (end - start) + "ms");
+ }
}
private static class TestThread implements Runnable {
private int count;
- private boolean useSync;
- private BenchmarkTest benchmarkTest;
-
- public TestThread(int count, boolean useSync, BenchmarkTest benchmarkTest) {
+ private Runnable test;
+
+ public TestThread(int count, Runnable test) {
this.count = count;
- this.useSync = useSync;
- this.benchmarkTest = benchmarkTest;
+ this.test = test;
}
-
+
public void run() {
for (int i = 0; i < count; i++) {
- if (useSync) {
- benchmarkTest.doSync();
- } else {
- benchmarkTest.doLocal();
- }
+ test.run();
}
}
-
}
}