Marc Baumbach
Marc Baumbach

Reputation: 10473

How to improve speed of DynamoDB requests

I've been testing out DynamoDB as a potential option for a scalable and steady throughput database for a site that will be hit pretty frequently and requires a very fast response time (< 50ms). I'm seeing pretty slow responses (both locally and on an EC2 instance) for the following code:

public static void main(String[] args) {
    try {
        AWSCredentials credentials = new PropertiesCredentials(new File("aws_credentials.properties"));
        long start = System.currentTimeMillis();
        AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials);
        System.out.println((System.currentTimeMillis() - start) + " (ms) to connect");
        DynamoDBMapper mapper = new DynamoDBMapper(client);
        start = System.currentTimeMillis();
        Model model = mapper.load(Model.class, "hashkey1", "rangekey1");
        System.out.println((System.currentTimeMillis() - start) + " (ms) to load Model");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

The connection to the DB alone takes about 800 (ms) on average and the loading using the mapper takes an additional 200 (ms). According to Amazon's page about DynamoDB we should expect "Average service-side latencies...typically single-digit milliseconds." I wouldn't expect the full round-trip HTTP request to add that much overhead. Are these expected numbers even on an EC2 instance?

Upvotes: 3

Views: 7410

Answers (2)

Sony Kadavan
Sony Kadavan

Reputation: 4072

Dynamo DB is located in a specific region (they dont yet support cross region replication). This is chosen by you when you create a table. Unless you are calling the APIs from the same region, it is bound to be slow.

It looks like you are trying to call Dynamo from your development desktop. You can re-do the same test from an EC2 instance started in the "same region". This will considerably speed up the responses. This is a more realistic test, since any way when you deploy your production system it will be in the same region as Dynamo.

Again, if you really need very quick response, consider using ElastiCache between your code and Dynamo. On every read, store on cache before returning the results. Next read should read from the cache (say for an expiry time of 10 mins). For "read-heavy" apps this is the suggested route. I have seen many fold better response using this approach.

Upvotes: 3

Hanson Char
Hanson Char

Reputation: 231

I think a better test would be to avoid the initial costs/latency incurred in starting up the JVM and loading the classes. Something like:

public class TestDynamoDBMain {
    public static void main(String[] args) {
        try {
            AWSCredentials credentials = new PropertiesCredentials(new File("aws_credentials.properties"));
            AmazonDynamoDBClient client = new AmazonDynamoDBClient(credentials);
            DynamoDBMapper mapper = new DynamoDBMapper(client);
            // Warm up
            for (int i=0; i < 10; i++) {
                testrun(mapper, false);
            }
            // Time it
            for (int i=0; i < 10; i++) {
                testrun(mapper, true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }

    private static void testrun(DynamoDBMapper mapper, boolean timed) {
        long start = System.nanoTime();
        Model model = mapper.load(Model.class, "hashkey1", "rangekey1");
        if (timed)
            System.out.println(
                TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)
                + " (ms) to load Model");
    }
}

Furthermore, you may consider enabling the default metrics of the AWS SDK for Java to see the fine grain time allocation in Amazon CloudWatch. For more details, see:

http://java.awsblog.com/post/Tx1O0S3I51OTZWT/Taste-of-JMX-Using-the-AWS-SDK-for-Java

Hope this helps.

Upvotes: 4

Related Questions