[
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