USA Spending Client Caching

The USA Spending Client version comes with caching functionality that will increase performance significanly for applications that make repeated calls to the USASpending.gov website for the same data.

The Results

Below we have a table which contains a side-by-side comparison between the performance of the USA Spending Client without caching and with caching enabled.

Note that in each example we make the call five times.

NameValue without caching (ms)Value with caching (ms)
LastValue4286.025.0
Avg4685.4998.0
Total23427.04990.0

How It Works

When the application invokes the doGet method on the QueryBuilder a URI is created and we can use this URI as a key, since it is unique and will be associated with exactly one object.

An attempt will be made to lookup the object associated with this key in the cache — if a non-null reference is returned, then no call to the USA Spending Client is executed since the application already has this result in memory, otherwise the web service call is made and the resultant object is added to the cache using the URI as a key — the object is then returned to the caller.

The script we used to perform this test was executed in the demonstration application and is shown here:

import com.coherentlogic.usaspending.client.core.domain.Complete
import com.coherentlogic.usaspending.client.core.builders.Detail

return queryBuilder
    .fsrs()
    .setFiscalYear("2000")
    .setStateCode("TX")
    .setDetail(Detail.complete)
    .setMaxRecords(500)
    .doGet(Complete.class);

The URI that this script generates is below and this can be used as a key:

http://www.usaspending.gov/fsrs/fsrs.php?fiscal_year=2000&stateCode=TX&detail=c&max_records=500

In this example we used a simple HashMap to cache calls to the USASpending.gov website. While a HashMap may be appropriate for a simple test like this, a serious application would want to evict data from the cache every now and then, as well as take advantage of other features that a full-blown cache such as JBoss Infinispan, Oracle Coherence, GigaSpaces, IBM WebSphere eXtreme Scale, etc. provide.

Note that the cache is passed in to the QueryBuilder via a constructor parameter — the example below demonstrates how this is accomplished.

Map cache = new HashMap ();

CacheServiceProviderSpecification cacheProvider =
    new MapCompliantCacheServiceProvider (cache);

QueryBuilder queryBuilder = new QueryBuilder (restTemplate, uri, cacheProvider);