Caching Example II Appropriate Data Structures and Algorithms

- 243 - o0 = plain_accessa9; } System.out.printlnplain access took + System.currentTimeMillis -time; time = System.currentTimeMillis ; for int i = 0; i 1000000; i++ { o1 = cached_accessa0; o2 = cached_accessa1; o3 = cached_accessa2; o4 = cached_accessa3; o5 = cached_accessa4; o6 = cached_accessa5; o7 = cached_accessa6; o8 = cached_accessa7; o9 = cached_accessa8; o0 = cached_accessa9; } System.out.printlncached access took + System.currentTimeMillis -time; } }

11.6 Caching Example II

In a second example, we add an instance variable to the keys to provide the mapping into the cache. This example uses a circular cache that holds just the last most recent 128 keys accessed. This has an even larger speedup than the previous example, due to more optimal cache access: package tuning.cache; import java.util.Hashtable; import java.lang.Math; public class Test2 { The cache array for the keys static Test2[] cache_keys = new Test2[128]; The array for the values corresponding to cached keys static Object[] cache_values = new Object[128]; static Hashtable hash = new Hashtable ; The index to use for the next object added to the cache static int freeIndex = 0; The current index in the cache referenced by this object int cacheRef = -1; Unique integer for each object, can be used as hash code int value; public static void mainString[] args { try { System.out.printlnstarted populating; populate ; System.out.printlnstarted accessing; access_test ; } - 244 - catchException e{e.printStackTrace ;} } public Test2int i { value = i; } public int hashCode { return value; } public boolean equalsObject obj { Equality test requires null check, type check, and value check if obj = null obj instanceof Test2 return value == Test2 obj.value; else return false; } public static void populate { for int i = 0; i 100000; i++ hash.putnew Test2i, new Integeri+5; } public static Object plain_accessTest2 i { return hash.geti; } public static Object cached_accessTest2 i { Access index into the cache is quick and easy to get int access = i.cacheRef; Object o; If it is -1 then it is not in the cache if access == -1 { get the object using the hash table o = hash.geti; Get the next available index in the cache. Wind round to the start of the cache if it is off the end if freeIndex = cache_keys.length freeIndex = 0; set the cache index; increment the next cache index too access = i.cacheRef = freeIndex++; If there was already something in the cache at that location, uncache it if cache_keys[access] = null { System.out.printlnCollsion between + cache_keys[access] + and + i; cache_keys[access].cacheRef = -1; } And cache our new value. cache_keys[access] = i; cache_values[access] = o; return o; } else { - 245 - return cache_values[access]; } } public static void access_test { Test2 a0 = new Test26767676; Test2 a1 = new Test233; Test2 a2 = new Test2998; Test2 a3 = new Test23333; Test2 a4 = new Test212348765; Test2 a5 = new Test29999; Test2 a6 = new Test266665; Test2 a7 = new Test21234; Test2 a8 = new Test2987654; Test2 a9 = new Test23121219; Object o1,o2,o3,o4,o5,o6,o7,o8,o9,o0; long time = System.currentTimeMillis ; for int i = 0; i 1000000; i++ { o1 = plain_accessa0; o2 = plain_accessa1; o3 = plain_accessa2; o4 = plain_accessa3; o5 = plain_accessa4; o6 = plain_accessa5; o7 = plain_accessa6; o8 = plain_accessa7; o9 = plain_accessa8; o0 = plain_accessa9; } System.out.printlnplain access took + System.currentTimeMillis -time; time = System.currentTimeMillis ; for int i = 0; i 1000000; i++ { o1 = cached_accessa0; o2 = cached_accessa1; o3 = cached_accessa2; o4 = cached_accessa3; o5 = cached_accessa4; o6 = cached_accessa5; o7 = cached_accessa6; o8 = cached_accessa7; o9 = cached_accessa8; o0 = cached_accessa9; } System.out.printlncached access took + System.currentTimeMillis -time; } } These are examples of general data caching. Sometimes you will know beforehand exactly which objects will be frequently accessed. In this case, you can create a specialized class that provides an accessor that optimizes access for just these objects. This can be as simple as a switch statement or multiple if statements. For example: public Object getObject key { - 246 - if key == FAST_KEY1 return value1; else if key.equalsFASTISH_KEY2 return value2; else if key.equalspossibly_fast_key_assigned_at_runtime return value3; else return hash.getkey; }

11.7 Finding the Index for Partially Matched Strings