JT in Helsinki

Home About RSS

Object Caching

  • code
  • design pattern
  • java
  • javascript
  • typescript

Retrieving data from a database is expensive because of issues such as network latency and query performance. Generally this is a big cost and the problem only increases as traffic goes up.

One of the easiest yet most effective ways of improving performance is through the use of caching and with a handful of lines of code a simple yet effective cache can be built. In Typescript (and JavaScript) and Java, (or any other language) the ideas are the similar. That is: the two steps are:

  1. Check the cache for the existence of the object in question
  2. if it does not exists, retrieve it from the database, add it to the cache and return the object to the user.

Generically speaking, this is known as the Identity Map pattern. Java implements this pattern using the java.util.IdentityHashMap class. Typescript/JavaScript has no such implementation but it’s easy enough to build one.

As described above, we want to be able to retrieve items from our Map and add items to our Map. Simple enough. Let’s have a look:

/**
 * A very simple identity map. Not a full implementation.
 */

export class IdentityMap {

    private map: Map<any, any> = new Map<any, any>();

    constructor(private databaseService: DatabaseService) {
    } 
    
    set(key: any, value: any): void {
        if (!this.has(key))
            this.map.set(key, value);

    }

    has(key: any): boolean {
        return this.map.has(key);
    }
    
    async get(key: any): any {
        if (hasKey(key))
            return this.map.get(value);

        // retrieve data from database  and return
        const value = await this.databaseService.getItem(key);
        this.set(key, value);
        return this.get(key);
    }
    
    remove(key: any): void {
        if (hasKey(key))
            this.map.delete(key)
    }

}

The simplicity of this class makes it easy to follow. Although this is by no means a proper implementation, it is clear to see that all it does is maintain a map of objects identified in some unique way. Each item retrieved from the database is stored in the map object for easy retrieval later.

Through implementing something along these lines, it is quite easy to improve the performance of an application whereby both database load and network traffic are reduced. In reality this class would be far more robust and depending on the number of objects stored you may employ a memory cache. Either way, the underlying ideas are the same.