Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Comments on this SizeOf Aspect?

Hi David -

An interesting crosscutting idea. Some comments:

To trade space for time in types ajc controls, use an instance variable
to store the size (instead of pertypewithing).  Results I got were:

Average cost for instance lookup : 0.0ms
Average cost for static lookup : 0.00561ms
Average cost for  cache lookup : 0.00991ms

(If you look at the implementation of pertypewithin, you might find a
map lookup, just like the cache implementation.)

The instance variable is declared on an interface (declared on your Test)
and initialized on construction:

final aspect BSizeOf extends SizeOf {
    public int ISize.size = SizeOf.get(this); // reusing other implementation
    declare parents: Test implements ISize;
    declare error: !within(BSizeOf) && set(int ISizeOf.size) : "pseudo-final";
}

Also, for the other implementations, I refactored the aspect to extend 
a class to make it more testable and the aspect clearer.  The aspect
result is

final aspect ASizeOf extends SizeOf pertypewithin(*) {

    after() : staticinitialization(*) {
        Class c = thisJoinPointStaticPart.getSignature().getDeclaringType();
        size = computeSize(c, null);
    }
}

Aside from a clearer aspect, it means clients bind to the class SizeOf 
rather than the aspect ASizeOf, which is often easier for maintenance.

Wes

P.P.S. - not in my code, but I would never use simple 'after()' advice
on staticinitialization, but would use 'after() returning' -- class
initialization is convoluted enough without advising abrupt completion.
Indeed, I'm not sure if your size computation handles a class that's not 
done initializing.  In a cycle where classes A -> B -> A, B will complete
initialization before A does, but your calc would need the (uninitialized) A.
That's not really an AspectJ issue, but you bump into it when advising
staticinitialization(..).

> ------------Original Message------------
> From: David Pearce <david.pearce@xxxxxxxxxxxxx>
> To: aspectj-users@xxxxxxxxxxx
> Date: Thu, Jan-19-2006 2:11 PM
> Subject: [aspectj-users] Comments on this SizeOf Aspect?
>
> Hi All,
> 
> I have just written a SizeOf Aspect using the new pertypewithin option 
> and i'm wondering whether anyone has any comments/suggestions on the 
> design ...
> 
> The problem is to write a "sizeof" method for Java (as close to the C 
> equivalent as possible).  The idea I originally envisaged was to 
> introduce a static int field into every class which could hold the 
> classes "sizeof" value.  The value itself being computed once during 
> static initialisation of the class.  This would give constant time 
> access to the sizeof information, which would be more efficient than 
> using, for example, a Map from Classes to Sizeof values.
> 
> While static introductions using wildcards are not possible in AspectJ 
> (see README-11.html), the new pertypewithin appears to be the answer. 
> The initial design looking like this:
> 
> > public aspect SizeOf pertypewithin(*) {
> >     private int size = -1;
> > 
> >     // is this the right way to do this?
> >     after() : staticinitialization(*) {	
> > 	size = computeSize(thisJoinPointStaticPart
> >                           .getSignature().getDeclaringType());
> >     }
> >     
> >     public static int get(Object o) { 
> > 	Class c = o.getClass(); 	
> >	SizeOf a = SizeOf.aspectOf(c);
> > 	return a.size;
> >     } 
> > }
> 
> For now, don't worry about how computeSize works (it uses reflection). 
> Basically, the size value is computed on static initialisation of a 
> type 
> and then stored in a field for constant-time access from get().  So, 
> for 
> a given Object o, the user can use the method SizeOf.get(o) to estimate 
> 
> the size in bytes of the object.
> 
> One problem, of course, is that many classes (e.g. arrays, classes in 
> the standard library) are not exposed to the weaver and, hence, are not 
> 
> matched by pertypewithin(*).  To get around this, I use a "back up" 
> cache for those types which have no aspect associated with them, giving 
> 
> the following:
> 
> > public aspect SizeOf pertypewithin(*) {
> >     static private Map cache = Collections.synchronizedMap(new 
> HashMap());
> >     private int size = -1;
> > 
> >     // is this the right way to do this?
> >     after() : staticinitialization(*) {	
> > 	size = computeSize(thisJoinPointStaticPart
>  >                          .getSignature().getDeclaringType(),null);
> >     }
> >     
> >     public static int get(Object o) { 
> > 	Class c = o.getClass();
> > 	
> > 	if(SizeOf.hasAspect(c)) {
> > 	    SizeOf a = SizeOf.aspectOf(c);
> > 	    return a.size;
> > 	} else {
> > 	    Integer r = (Integer) cache.get(c);
> > 	    if(r != null) { return r; }
> > 	    else {
> > 		int x = computeSize(c,o);
> > 		cache.put(c,x);
> > 		return x;
> > 	    } 
> > 	} 
> >   }
> 
> In get(), I pass the actual Object into computeSize() as well, so that 
> it can be used to determine the size of an array (for array types).
> 
> Anyway, I've attached the complete source, including a test harness as 
> a 
> tarball.  The test testharness performs some simple measurements of the 
> 
> time taken for a static lookup versus a cache lookup.  The results 
> suggest a static lookup is about twice as fast (on my machine, at 
> least).
> 
> So, finally, any comments on this design would be very much 
> appreciated!!  In particular, is there a better way to do this?
> 
> Cheers,
> 
> David J. Pearce
> 
> -- 
> Lecturer in Computer Science,
> School of Mathematics, Statistics and Computer Science,
> Victoria University of Wellington,
> PO Box 600,
> Wellington,
> New Zealand.
> 
> Office: Cotton 231
> Telephone: +64 4 463 5833
> URL: http://www.mcs.vuw.ac.nz/~djp
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
> 
> 

Attachment: sizeof-redux.zip
Description: Zip archive


Back to the top