200 likes | 394 Views
Caching: An Optimization Aspect. Class Diagram for Base. Back Item Target Container Source Caching Container C. contains. Item +name : String +check() : int. 0..*. Container +capacity : int +check() : int +addItem(Item it):void. Simple +weight : int +check() : int. Background.
E N D
Class Diagram for Base Back Item Target Container Source Caching Container C contains Item +name : String +check() : int 0..* Container +capacity : int +check() : int +addItem(Item it):void Simple +weight : int +check() : int
Background • Container/Simple both inherit from Item && Container contains vector of Item. • Cache the value of the sum for each container and the number of violations. • If the same container is checked again and there has been no change, we can reuse the cached values
Caching Aspect • Interface C (view it as a role) • Can have one of its methods cached • Requires a method allInvalidated: • Returns all objects whose caches would be invalidated by a modification to the current object • AspectJ interfaces can provide member implementations and fields: field cachedValue And method clearCache(){…} • Very useful! Define popular behaviors.
Reusable • Use abstract pointcuts to represent the methods to be cached (cachedmeth) and the methods to invalidate caches (invalidate). • Advice for those pointcuts.
Object • Object around(..) : cachedmeth … • Object cachedValue
Back Aspect • Want to maintain an invariant. • Intercept calls that can affect the invariant.
Old viewgraphs • Alternative solution
HashTable method • Hashtable cache=new Hashtable(); • pointcut changed(Container c):target(c) && call(* Container.addItem(..)); • before(Container c):changed(c){ if(cache.containsKey(c)){ Container contain=c.getContainer(); cache.remove(c); //invalidate while(contain!=null) { cache.remove(contain); contain=contain.getContainer();
pointcut getvalue(Item i):target(i) && call(* *.check(..)); • int around(Item i):getvalue(i){ if(cache.containsKey(i)) return ((Integer)cache.get(i)).intValue(); int v=thisJoinPoint.proceed(i); cache.put(i,new Integer(v)); return v;
Introductions • private int Container.violations = 0; • private int Container.total = 0; • private boolean Container.cacheIsValid = false;
pointcut getTotal(Container c): call (int check(..)) && target(c); • int around (Container c): getTotal(c){ if(c.cacheIsValid){ System.out.println(c.name + " using cached value for total: " + c.total); if(c.violations > 0){ System.out.println(c.name + " had " + c.violations + " violations"); return c.total; } else return proceed(c);
after(Container c) returning (int tot): getTotal(c){ c.total = tot; c.violations = c.total - c.capacity; c.cacheIsValid = true;}
Adding a new item: • pointcut newItem(Container c, Item i): call(void setContainer(..)) && target(i) && args(c); • after(Container c, Item i): newItem(c, i){ c.setValid(false); } • public void Container.setValid(boolean isValid){ cacheIsValid = isValid; if(getContainer() != null){ getContainer().setValid(isValid);
What was learned? • The Hashtable allows us to better encapsulate the Caching aspect, leaving us with more elegant code that doesn’t pollute the name-space of Container • It seems cleaner for each Container to keep track of its total weight. This will also probably shorten the run-time.
Part 1b/d: Improving modularity and reusability • If we don’t cache, we don’t need the back pointers in our containers. So make it an aspect! • Improve reusability through use of abstract aspects.
Back pointer: based on introductions • private Container Item.container; • public void Item.setContainer(Container c){ container = c;} • public Container Item.getContainer(){ return container;}
Setting the BP • pointcut addingItem(Container c, Item i): call (void addItem(..)) && target(c) && args(i); • after(Container c, Item i): addingItem(c, i){ i.setContainer(c); }
Abstract Caching Aspect • There is a Parent/Child relationship which can be useful in creating abstract aspects. • interface Parent extends Child{ void addItem(Child c); • abstract aspect Cashing{ abstract pointcut invalidate(Parent p); abstract pointcut cashing(Parent p);
Such that we can implement interesting functionality based • only on knowledge that a Parent/Child relationship exists. • after(Parent p): invalidate(p){ • while(p != null){ • beforeInvalidate(p); • p.cashedValue = -1; • p = ((Child)p).getParent(); • }