Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
research:software:reflex:documentation:cache_evaluation_aspect [2007/07/30 03:14] – admin | research:software:reflex:documentation:cache_evaluation_aspect [2007/08/24 22:01] (current) – rtoledo | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Cache Evaluation Aspect ====== | ||
+ | In the previous section we reviewed how to add a cache to our Fibonacci class. Now that we have the cache, a good question that may arise is: how effective is the cache?. In this section we will se how to define a new aspect: a cache evaluation aspect; that will monitor the execution of another aspect: the cache aspect. | ||
+ | |||
+ | First, we need to define how we are going to measure the cache efectiveness. The alternative we will take is to compare how many times the get method was called and how many times the cache aspect called proceed (this represents a cache miss). Then, we can calculate the cache efectiveness with the following formula: | ||
+ | |||
+ | < | ||
+ | cache efectiveness (%) = (theCalls - theMisses) / theCalls) * 100 | ||
+ | </ | ||
+ | That represents the percentage of cache hits ever the total get invocations. | ||
+ | |||
+ | As we have already developed a cache aspect, we will reuse its code (the version we chose is the one that uses the Fibonacci instances to hold the cached values): | ||
+ | <code java> | ||
+ | SMetaobject theSMO = new CacheElementsSMO(); | ||
+ | SLink theSLink = API.links().createSLink( | ||
+ | new NameCS(" | ||
+ | theSMO | ||
+ | ); | ||
+ | |||
+ | Hookset theHookset = new PrimitiveHookset( | ||
+ | MsgReceive.class, | ||
+ | new NameCS(" | ||
+ | new NameOS(" | ||
+ | ); | ||
+ | |||
+ | MODefinition theMO = new MODefinition.SharedMO(new GlobalCacheHandler()); | ||
+ | |||
+ | BLink theCacheLink = Links.get(theHookset, | ||
+ | theCacheLink.setControl(Control.AROUND); | ||
+ | theCacheLink.setCall(Control.AROUND, | ||
+ | new Parameter[]{ | ||
+ | | ||
+ | new StdParameters.IndexedArgument(0), | ||
+ | | ||
+ | }); | ||
+ | </ | ||
+ | (A detailled description of this code can be found in the previous [[Cache Aspect|section]]) | ||
+ | |||
+ | The metaobject we will use to record the statistics is defined this way: | ||
+ | <code java> | ||
+ | public static class EvalCacheMO{ | ||
+ | |||
+ | private int itsCalls = 0; | ||
+ | private int itsCacheMisses = 0; | ||
+ | |||
+ | public void enterGet(){ | ||
+ | //record that the get method was called | ||
+ | } | ||
+ | |||
+ | public Object cacheMiss(IExecutionPointClosure aClosure){ | ||
+ | //record that the cache failed and proceed | ||
+ | } | ||
+ | |||
+ | public int getCacheMisses(){ | ||
+ | return itsCacheMisses; | ||
+ | } | ||
+ | |||
+ | public int getCalls(){ | ||
+ | return itsCalls; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | As you can see, it only holds the two values representing the number of calls to the get method and the number of cache misses. We will review now the how the methods enterGet and cacheMiss are invoked and what they do in their bodies. | ||
+ | |||
+ | First, the metaobject definition: | ||
+ | <code java> | ||
+ | EvalCacheMO theEvalCacheMO = new EvalCacheMO(); | ||
+ | MODefinition theEvalMO = new MODefinition.SharedMO(theEvalCacheMO); | ||
+ | </ | ||
+ | Now, to make the enterGet method be called, we put a link with '' | ||
+ | <code java> | ||
+ | BLink theEnterGetLink = Links.get(theHookset, | ||
+ | theEnterGetLink.setControl(Control.BEFORE); | ||
+ | theEnterGetLink.setCall(Control.BEFORE, | ||
+ | </ | ||
+ | This code is self-explanatory: | ||
+ | |||
+ | Now, and this is the difficult part, we need to make the '' | ||
+ | <code java> | ||
+ | BLink theCacheMissLink = Links.get(theHookset, | ||
+ | theCacheMissLink.setControl(Control.AROUND); | ||
+ | theCacheMissLink.setCall( | ||
+ | Control.AROUND, | ||
+ | EvalCacheMO.class.getName(), | ||
+ | " | ||
+ | Parameter.CLOSURE) | ||
+ | ); | ||
+ | </ | ||
+ | |||
+ | Here we create a link, with '' | ||
+ | * theCacheLink: | ||
+ | * theEnterGetLink: | ||
+ | * theCacheMissLink: | ||
+ | |||
+ | The first two links can be composed without problems: first behavior assosiated with '' | ||
+ | |||
+ | But in this case, wo have two links with '' | ||
+ | |||
+ | In our case we want the '' | ||
+ | |||
+ | Then, there is only one configuration instruction remaining: | ||
+ | <code java> | ||
+ | API.rules().addRule(new Wrap(theCacheLink, | ||
+ | </ | ||
+ | |||
+ | {info} | ||
+ | The code above specifies that the '' | ||
+ | |||
+ | |||
+ | Finally, we add a shutdown hook at the virtual machine level to print the cache statistics right before the end of the program (in a real application, | ||
+ | <code java> | ||
+ | Runtime.getRuntime().addShutdownHook(new Thread(){ | ||
+ | |||
+ | public void run(){ | ||
+ | int theCalls = theEvalCacheMO.getCalls(); | ||
+ | int theMisses = theEvalCacheMO.getCacheMisses(); | ||
+ | |||
+ | System.out.println(" | ||
+ | System.out.println(" | ||
+ | | ||
+ | System.out.println(" | ||
+ | | ||
+ | System.out.println(" | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | }); | ||
+ | </ | ||
+ | |||
+ | The complete code of this example is [[http:// | ||
+ | < | ||
+ | Windows | ||
+ | %java -classpath | ||
+ | " | ||
+ | reflex.examples.tutorial.CacheEvaluationAspect | ||
+ | |||
+ | Linux | ||
+ | %java -classpath | ||
+ | " | ||
+ | reflex.examples.tutorial.CacheEvaluationAspect | ||
+ | </ | ||
+ | |||
+ | If everithing went ok, the output should be something like: | ||
+ | < | ||
+ | The fibonacci[5] is 5 | ||
+ | |||
+ | The fibonacci[6] is 8 | ||
+ | |||
+ | ------ Cache Evaluation --------- | ||
+ | | ||
+ | Cache misses | ||
+ | Cache effectiveness: | ||
+ | --------------------------------- | ||
+ | </ | ||
+ | You can see here that the effectiveness of our cache strategy is 35%. Not so bad ;-). |