Modified DateService to be explicit about date formats, and to use SimpleDateFormat when it's faster. Also modified test to better check thread safety and provide *unreliable* performance feedback

git-svn-id: http://jclouds.googlecode.com/svn/trunk@826 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
jamurty 2009-05-22 00:57:03 +00:00
parent 60c25b0a8d
commit c6adc326bc
12 changed files with 320 additions and 130 deletions

View File

@ -110,7 +110,7 @@ public class ParseMetadataFromHeaders extends
String lastModified = getResponse().getFirstHeaderOrNull( String lastModified = getResponse().getFirstHeaderOrNull(
HttpHeaders.LAST_MODIFIED); HttpHeaders.LAST_MODIFIED);
metadata.setLastModified(dateParser metadata.setLastModified(dateParser
.dateTimeFromHeaderFormat(lastModified)); .rfc822DateParse(lastModified));
if (metadata.getLastModified() == null) if (metadata.getLastModified() == null)
throw new HttpException("could not parse: " throw new HttpException("could not parse: "
+ HttpHeaders.LAST_MODIFIED + ": " + lastModified); + HttpHeaders.LAST_MODIFIED + ": " + lastModified);

View File

@ -179,7 +179,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
checkState(getIfUnmodifiedSince() == null, checkState(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()"); "ifUnmodifiedSince() is not compatible with ifModifiedSince()");
replaceHeader("x-amz-copy-source-if-modified-since", replaceHeader("x-amz-copy-source-if-modified-since",
dateService.toHeaderString(checkNotNull(ifModifiedSince, dateService.rfc822DateFormat(checkNotNull(ifModifiedSince,
"ifModifiedSince"))); "ifModifiedSince")));
return this; return this;
} }
@ -196,7 +196,7 @@ public class CopyObjectOptions extends BaseHttpRequestOptions {
checkState(getIfModifiedSince() == null, checkState(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()"); "ifModifiedSince() is not compatible with ifUnmodifiedSince()");
replaceHeader("x-amz-copy-source-if-unmodified-since", dateService replaceHeader("x-amz-copy-source-if-unmodified-since", dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince, .rfc822DateFormat(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince"))); "ifUnmodifiedSince")));
return this; return this;
} }

View File

@ -124,7 +124,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
checkArgument(getIfUnmodifiedSince() == null, checkArgument(getIfUnmodifiedSince() == null,
"ifUnmodifiedSince() is not compatible with ifModifiedSince()"); "ifUnmodifiedSince() is not compatible with ifModifiedSince()");
this.headers.put(HttpHeaders.IF_MODIFIED_SINCE, this.headers.put(HttpHeaders.IF_MODIFIED_SINCE,
dateService.toHeaderString(checkNotNull(ifModifiedSince, dateService.rfc822DateFormat(checkNotNull(ifModifiedSince,
"ifModifiedSince"))); "ifModifiedSince")));
return this; return this;
} }
@ -153,7 +153,7 @@ public class GetObjectOptions extends BaseHttpRequestOptions {
checkArgument(getIfModifiedSince() == null, checkArgument(getIfModifiedSince() == null,
"ifModifiedSince() is not compatible with ifUnmodifiedSince()"); "ifModifiedSince() is not compatible with ifUnmodifiedSince()");
this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService this.headers.put(HttpHeaders.IF_UNMODIFIED_SINCE, dateService
.toHeaderString(checkNotNull(ifUnmodifiedSince, .rfc822DateFormat(checkNotNull(ifUnmodifiedSince,
"ifUnmodifiedSince"))); "ifUnmodifiedSince")));
return this; return this;
} }

View File

@ -81,7 +81,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter {
// amazon is ok with up to 15 minutes off their time, so let's // amazon is ok with up to 15 minutes off their time, so let's
// be as lazy as possible. // be as lazy as possible.
String createNewStamp() { String createNewStamp() {
return dateService.timestampAsHeaderString(); return dateService.rfc822DateFormat();
} }
public String timestampAsHeaderString() { public String timestampAsHeaderString() {

View File

@ -23,35 +23,103 @@
*/ */
package org.jclouds.aws.s3.util; package org.jclouds.aws.s3.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
/** /**
* Parses dates found in XML responses and HTTP response headers. * Parses and formats the ISO8601 and RFC822 date formats found in
* XML responses and HTTP response headers.
* <p>
* Either {@link SimpleDateFormat} or {@link DateTimeFormatter}
* classes are used internally, depending on which version gives
* the best performance.
* *
* @author Adrian Cole * @author Adrian Cole
* * @author James Murty
*/ */
public class DateService { @ThreadSafe
private DateTimeFormatter headerDateFormat = DateTimeFormat public class DateService {
.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'"); /*
* Use default Java Date/SimpleDateFormat classes for date
* manipulation, but be *very* careful to guard against
* the lack of thread safety.
*/
@GuardedBy("this")
private static final SimpleDateFormat iso8601SimpleDateFormat =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
public DateTime dateTimeFromXMLFormat(String toParse) { @GuardedBy("this")
// the format is natively parseable from the DateTime constructor private static final SimpleDateFormat rfc822SimpleDateFormat =
return new DateTime(toParse); new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
private static final DateTimeFormatter iso8601DateTimeFormatter =
DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.withLocale(Locale.US).withZone(DateTimeZone.forID("GMT"));
private static final DateTimeFormatter rfc822DateTimeFormatter =
DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'")
.withLocale(Locale.US).withZone(DateTimeZone.forID("GMT"));
static {
iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
rfc822SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
}
public final String rfc822DateFormat(DateTime dateTime) {
return rfc822DateTimeFormatter.print(dateTime);
} }
public DateTime dateTimeFromHeaderFormat(String toParse) { public final String rfc822DateFormat(Date date) {
return headerDateFormat.parseDateTime(toParse); return rfc822DateFormat(new DateTime(date));
} }
public String timestampAsHeaderString() { public final String rfc822DateFormat() {
return toHeaderString(new DateTime()); return rfc822DateFormat(new DateTime());
}
public final DateTime rfc822DateParse(String toParse) {
synchronized (rfc822SimpleDateFormat) {
try {
return new DateTime(rfc822SimpleDateFormat.parse(toParse));
} catch (ParseException e) {
return null;
}
}
} }
public String toHeaderString(DateTime date) { public final String iso8601DateFormat(DateTime dateTime) {
return headerDateFormat.print(date.withZone(DateTimeZone.UTC)); return iso8601DateTimeFormatter.print(dateTime);
} }
public final String iso8601DateFormat(Date date) {
return iso8601DateFormat(new DateTime(date));
}
public final String iso8601DateFormat() {
return iso8601DateFormat(new DateTime());
}
public final DateTime iso8601DateParse(String toParse) {
synchronized (iso8601SimpleDateFormat) {
try {
return new DateTime(iso8601SimpleDateFormat.parse(toParse));
} catch (ParseException e) {
return null;
}
}
}
} }

View File

@ -62,7 +62,7 @@ public class CopyObjectHandler extends
.replaceAll("\"", ""))); .replaceAll("\"", "")));
} else if (qName.equals("LastModified")) { } else if (qName.equals("LastModified")) {
metadata.setLastModified(dateParser metadata.setLastModified(dateParser
.dateTimeFromXMLFormat(currentText.toString())); .iso8601DateParse(currentText.toString()));
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -73,7 +73,7 @@ public class ListAllMyBucketsHandler extends
currentS3Bucket = new S3Bucket.Metadata(currentText.toString()); currentS3Bucket = new S3Bucket.Metadata(currentText.toString());
} else if (qName.equals("CreationDate")) { } else if (qName.equals("CreationDate")) {
currentS3Bucket.setCreationDate(dateParser currentS3Bucket.setCreationDate(dateParser
.dateTimeFromXMLFormat(currentText.toString())); .iso8601DateParse(currentText.toString()));
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -82,7 +82,7 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<S3Bucket> {
.toString()); .toString());
} else if (qName.equals("LastModified")) { } else if (qName.equals("LastModified")) {
currentObjectMetadata.setLastModified(dateParser currentObjectMetadata.setLastModified(dateParser
.dateTimeFromXMLFormat(currentText.toString())); .iso8601DateParse(currentText.toString()));
} else if (qName.equals("ETag")) { } else if (qName.equals("ETag")) {
currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText currentObjectMetadata.setMd5(S3Utils.fromHexString(currentText
.toString().replaceAll("\"", ""))); .toString().replaceAll("\"", "")));

View File

@ -348,13 +348,13 @@ public class StubS3Connection implements S3Connection {
throwResponseException(412); throwResponseException(412);
} }
if (options.getIfModifiedSince() != null) { if (options.getIfModifiedSince() != null) {
DateTime modifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfModifiedSince()); DateTime modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
if (modifiedSince.isAfter(object.getMetadata().getLastModified())) if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after")); throw new ExecutionException(new RuntimeException("after"));
} }
if (options.getIfUnmodifiedSince() != null) { if (options.getIfUnmodifiedSince() != null) {
DateTime unmodifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfUnmodifiedSince()); DateTime unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified())) if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after")); throw new ExecutionException(new RuntimeException("after"));
} }
@ -435,13 +435,13 @@ public class StubS3Connection implements S3Connection {
throwResponseException(304); throwResponseException(304);
} }
if (options.getIfModifiedSince() != null) { if (options.getIfModifiedSince() != null) {
DateTime modifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfModifiedSince()); DateTime modifiedSince = dateService.rfc822DateParse(options.getIfModifiedSince());
if (modifiedSince.isAfter(object.getMetadata().getLastModified())) if (modifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after")); throw new ExecutionException(new RuntimeException("after"));
} }
if (options.getIfUnmodifiedSince() != null) { if (options.getIfUnmodifiedSince() != null) {
DateTime unmodifiedSince = dateService.dateTimeFromHeaderFormat(options.getIfUnmodifiedSince()); DateTime unmodifiedSince = dateService.rfc822DateParse(options.getIfUnmodifiedSince());
if (unmodifiedSince.isAfter(object.getMetadata().getLastModified())) if (unmodifiedSince.isAfter(object.getMetadata().getLastModified()))
throw new ExecutionException(new RuntimeException("after")); throw new ExecutionException(new RuntimeException("after"));
} }

View File

@ -59,7 +59,7 @@ public class CopyObjectOptionsTest {
badMeta.put("x-google-meta-adrian", "foo"); badMeta.put("x-google-meta-adrian", "foo");
now = new DateTime(); now = new DateTime();
nowExpected = new DateService().toHeaderString(now); nowExpected = new DateService().rfc822DateFormat(now);
testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7}; testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
} }
@ -299,7 +299,7 @@ public class CopyObjectOptionsTest {
.ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith( .ifSourceMd5DoesntMatch(testBytes).overrideMetadataWith(
goodMeta).buildRequestHeaders(); goodMeta).buildRequestHeaders();
assertEquals(headers.get("x-amz-copy-source-if-modified-since") assertEquals(headers.get("x-amz-copy-source-if-modified-since")
.iterator().next(), new DateService().toHeaderString(now)); .iterator().next(), new DateService().rfc822DateFormat(now));
assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator() assertEquals(headers.get("x-amz-copy-source-if-none-match").iterator()
.next(), "\"" + S3Utils.toHexString(testBytes) + "\""); .next(), "\"" + S3Utils.toHexString(testBytes) + "\"");
for (String value : goodMeta.values()) for (String value : goodMeta.values())

View File

@ -49,7 +49,7 @@ public class GetObjectOptionsTest {
@BeforeTest @BeforeTest
void setUp() { void setUp() {
now = new DateTime(); now = new DateTime();
nowExpected = new DateService().toHeaderString(now); nowExpected = new DateService().rfc822DateFormat(now);
testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7}; testBytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7};
} }

View File

@ -23,161 +23,283 @@
*/ */
package com.amazon.s3; package com.amazon.s3;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.DateService;
import org.joda.time.DateTime;
import org.testng.annotations.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService; import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
import org.jclouds.aws.PerformanceTest;
import org.jclouds.aws.s3.util.DateService;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/*
* TODO: Scrap any non-DateService references (eg Joda & Amazon) if/when
* we confirm that using the Java primitives is better/faster.
*/
/** /**
* Compares performance of date operations * Compares performance of date operations
* *
* @author Adrian Cole * @author Adrian Cole
* @author James Murty
*/ */
@Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.DateTest") @Test(sequential = true, timeOut = 2 * 60 * 1000, testName = "s3.DateTest")
public class DateServiceTest extends PerformanceTest { public class DateServiceTest extends PerformanceTest {
Injector i = Guice.createInjector(); Injector i = Guice.createInjector();
DateService utils = i.getInstance(DateService.class); DateService dateService = i.getInstance(DateService.class);
SimpleDateFormat dateParser;
private TestData[] testData;
class TestData {
public final String iso8601DateString;
public final String rfc822DateString;
public final Date date;
TestData(String iso8601, String rfc822, Date date) {
this.iso8601DateString = iso8601;
this.rfc822DateString = rfc822;
this.date = date;
}
}
private long startTime;
public DateServiceTest() { public DateServiceTest() {
this.dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // Constant time test values, each TestData item must contain matching times!
this.dateParser.setTimeZone(new SimpleTimeZone(0, "GMT")); testData = new TestData[] {
new TestData("2009-03-12T02:00:07.000Z", "Thu, 12 Mar 2009 02:00:07 GMT", new Date(1236823207000l)),
new TestData("2009-03-14T04:00:07.000Z", "Sat, 14 Mar 2009 04:00:07 GMT", new Date(1237003207000l)),
new TestData("2009-03-16T06:00:07.000Z", "Mon, 16 Mar 2009 06:00:07 GMT", new Date(1237183207000l)),
new TestData("2009-03-18T08:00:07.000Z", "Wed, 18 Mar 2009 08:00:07 GMT", new Date(1237363207000l)),
new TestData("2009-03-20T10:00:07.000Z", "Fri, 20 Mar 2009 10:00:07 GMT", new Date(1237543207000l))
};
}
// Joda items for performance comparisons
private DateTimeFormatter headerDateFormat = DateTimeFormat
.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'");
private DateTime jodaParseIso8601(String toParse) {
return new DateTime(toParse);
} }
Date amazonDateFromString(String toParse) throws ParseException { private DateTime jodaParseRfc822(String toParse) {
return this.dateParser.parse(toParse); return headerDateFormat.parseDateTime(toParse);
} }
private static String toParse = "2009-03-12T02:00:07.000Z"; private String timestampAsHeaderString() {
return toHeaderString(new DateTime());
}
private String toHeaderString(DateTime date) {
return headerDateFormat.print(date.withZone(DateTimeZone.UTC));
}
private void startClock() {
startTime = System.currentTimeMillis();
}
private void printElapsedClockTime(String testName) {
System.out.println(testName + " took " +
(System.currentTimeMillis() - startTime) + "ms for "
+ LOOP_COUNT+ " loops");
}
@Test @Test
public void testParseDateSameAsAmazon() throws ParseException, public void testIso8601DateParse() throws ExecutionException,
ExecutionException, InterruptedException { InterruptedException
Date java = dateParser.parse(toParse); {
DateTime joda = utils.dateTimeFromXMLFormat(toParse); DateTime dsDate = dateService.iso8601DateParse(testData[0].iso8601DateString);
assert java.equals(joda.toDate()); assert testData[0].date.equals(dsDate.toDate());
} }
@Test @Test
public void testTimeStampDateSameAsAmazon() throws ExecutionException, public void testRfc822DateParse() throws ExecutionException,
InterruptedException { InterruptedException
String java = AWSAuthConnection.httpDate(); {
String joda = utils.timestampAsHeaderString(); DateTime dsDate = dateService.rfc822DateParse(testData[0].rfc822DateString);
assert java.equals(joda); assert testData[0].date.equals(dsDate.toDate());
} }
@Test @Test
public void testToHeaderString() throws ExecutionException, public void testIso8601DateFormat() throws ExecutionException,
InterruptedException { InterruptedException
String joda1 = utils.toHeaderString(new DateTime()); {
String joda = utils.timestampAsHeaderString(); String dsString = dateService.iso8601DateFormat(testData[0].date);
assert joda1.equals(joda); assert testData[0].iso8601DateString.equals(dsString);
} }
@Test @Test
void testTimeStampSerialResponseTime() throws ExecutionException, public void testRfc822DateFormat() throws ExecutionException,
InterruptedException { InterruptedException
for (int i = 0; i < LOOP_COUNT; i++) {
utils.timestampAsHeaderString(); String dsString = dateService.rfc822DateFormat(testData[0].date);
assert testData[0].rfc822DateString.equals(dsString);
} }
@Test @Test
void testAmazonTimeStampSerialResponseTime() { void testIso8601DateFormatResponseTime() throws ExecutionException,
for (int i = 0; i < LOOP_COUNT; i++) InterruptedException {
AWSAuthConnection.httpDate(); for (int i = 0; i < LOOP_COUNT; i++)
dateService.iso8601DateFormat();
} }
@Test @Test
void testTimeStampParallelResponseTime() throws InterruptedException, void testRfc822DateFormatResponseTime() throws ExecutionException,
ExecutionException { InterruptedException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>( for (int i = 0; i < LOOP_COUNT; i++)
exec); dateService.rfc822DateFormat();
for (int i = 0; i < LOOP_COUNT; i++) }
completer.submit(new Callable<Boolean>() {
public Boolean call() throws ExecutionException, @Test
InterruptedException { void testFormatIso8601DateInParallel() throws InterruptedException,
utils.timestampAsHeaderString(); ExecutionException {
return true; CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
} exec);
}); startClock();
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++) {
assert completer.take().get(); final TestData myData = testData[i % testData.length];
completer.submit(new Callable<Boolean>() {
public Boolean call() throws ExecutionException,
InterruptedException
{
String dsString = dateService.iso8601DateFormat(myData.date);
/*
* Comment-in the assert below to test thread safety.
* Comment it out to test performance
*/
assert myData.iso8601DateString.equals(dsString);
return true;
}
});
}
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
printElapsedClockTime("testFormatIso8601DateInParallel");
} }
@Test @Test
void testAmazonTimeStampParallelResponseTime() throws InterruptedException, void testFormatAmazonDateInParallel() throws InterruptedException,
ExecutionException { ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>( CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec); exec);
for (int i = 0; i < LOOP_COUNT; i++) startClock();
completer.submit(new Callable<Boolean>() { for (int i = 0; i < LOOP_COUNT; i++)
public Boolean call() { completer.submit(new Callable<Boolean>() {
AWSAuthConnection.httpDate(); public Boolean call() {
return true; AWSAuthConnection.httpDate();
} return true;
}); }
for (int i = 0; i < LOOP_COUNT; i++) });
assert completer.take().get(); for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
printElapsedClockTime("testFormatAmazonDateInParallel");
} }
@Test @Test
void testParseDateSerialResponseTime() throws ExecutionException, void testFormatJodaDateInParallel() throws InterruptedException,
InterruptedException { ExecutionException {
for (int i = 0; i < LOOP_COUNT; i++) CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
utils.dateTimeFromXMLFormat(toParse); exec);
startClock();
for (int i = 0; i < LOOP_COUNT; i++) {
final TestData myData = testData[i % testData.length];
completer.submit(new Callable<Boolean>() {
public Boolean call() {
String jodaString = toHeaderString(new DateTime(myData.date));
assert myData.rfc822DateString.equals(jodaString);
return true;
}
});
}
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
printElapsedClockTime("testFormatJodaDateInParallel");
}
@Test
void testIso8601ParseDateSerialResponseTime() throws ExecutionException,
InterruptedException {
for (int i = 0; i < LOOP_COUNT; i++)
dateService.iso8601DateParse(testData[0].iso8601DateString);
} }
@Test @Test
void testAmazonParseDateSerialResponseTime() { void testAmazonParseDateSerialResponseTime() {
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)
AWSAuthConnection.httpDate(); AWSAuthConnection.httpDate();
} }
@Test @Test
void testParseDateParallelResponseTime() throws InterruptedException, void testParseIso8601DateInParallel() throws InterruptedException,
ExecutionException { ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>( CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec); exec);
startClock();
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++) {
completer.submit(new Callable<Boolean>() { final TestData myData = testData[i % testData.length];
public Boolean call() throws ExecutionException, completer.submit(new Callable<Boolean>() {
InterruptedException { public Boolean call() throws ExecutionException,
utils.dateTimeFromXMLFormat(toParse); InterruptedException {
return true; DateTime dsDate = dateService.iso8601DateParse(myData.iso8601DateString);
} assert myData.date.equals(dsDate.toDate());
}); return true;
for (int i = 0; i < LOOP_COUNT; i++) }
assert completer.take().get(); });
}
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
printElapsedClockTime("testParseIso8601DateInParallel");
} }
@Test @Test
void testAmazonParseDateParallelResponseTime() throws InterruptedException, void testParseAmazonDateInParallel() throws InterruptedException,
ExecutionException { ExecutionException {
CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>( CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
exec); exec);
startClock();
for (int i = 0; i < LOOP_COUNT; i++)
completer.submit(new Callable<Boolean>() {
public Boolean call() {
AWSAuthConnection.httpDate();
return true;
}
});
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
printElapsedClockTime("testParseAmazonDateInParallel");
}
for (int i = 0; i < LOOP_COUNT; i++) @Test
completer.submit(new Callable<Boolean>() { void testParseJodaDateInParallel() throws InterruptedException,
public Boolean call() { ExecutionException {
AWSAuthConnection.httpDate(); CompletionService<Boolean> completer = new ExecutorCompletionService<Boolean>(
return true; exec);
} startClock();
}); for (int i = 0; i < LOOP_COUNT; i++) {
for (int i = 0; i < LOOP_COUNT; i++) final TestData myData = testData[i % testData.length];
assert completer.take().get(); completer.submit(new Callable<Boolean>() {
public Boolean call() {
Date jodaDate = jodaParseIso8601(myData.iso8601DateString).toDate();
assert myData.date.equals(jodaDate);
return true;
}
});
}
for (int i = 0; i < LOOP_COUNT; i++)
assert completer.take().get();
printElapsedClockTime("testParseJodaDateInParallel");
} }
} }