Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Are aspects examining the running of Threads "special" in some way for AspectJ?

Hi,

On 27 April 2012 17:53, trhouse <trhouse@xxxxxxxxx> wrote:
> Regarding the empty advice,  I I did try empty advice (and also no advice)
> just to try to establish a baseline performance which was unaffected by
> aspectJ. When I did this, I wondered if "empty advice" was perhaps optimized
> by the AspectJ runtime into  "no advice" and therefore couldn't be used as a
> real baseline for "minimal overhead imposed by AspectJ."

empty advice is not optimized to no advice.  It could be, but we
assume users are never writing no-advice and thus it provides a useful
way to discover the baseline for the cost of just advice
instrumentation.

> So what you seem to be saying is "even when the advice is empty, AspectJ is
> still processing classes as their loaded". Is that correct? That's a useful
> bit of information to have if it's true.

No checks are made to see if your advice is empty.  What is important
are the pointcuts attached to the advice. Your pointcut is evaluated
against every potential match.  It will either fully match, absolutely
not match or partially match - in a full match the call to your advice
is inserted in the code.   In a partial match a test is inserted into
the code (that will execute at runtime) which determines if it is an
actual match - if it is then the advice is called.  What kind of test?
 Perhaps something like an 'instanceof'.
There are some timer options you can use where AspectJ will tell you
which pointcuts are 'expensive' and slowing down your weaving/startup
time: http://andrewclement.blogspot.com/2009/11/aspectj-profiling-pointcut-matching.html

> I also thought knowing whether limiting the joinpoints the pointcut woudl
> apply to could possibly limit the runtime overhead of applying the advice.
> For instance, if I explicitly limit the pointcut to joinpoints in a specific
> package, a statically determinable thing, does this help the LoadtimeWeaver
> in terms of enabling it to make fast rejections of other packages?

Absolutely, if you target your pointcuts AspectJ will do everything it
can to skip packages/types that can't possibly match.

> But why? Why did an uncaught exception not blow the program stack but instead cause it to, it seems, do a really
> just a ton of processing resulting in the observed behaviour? Is this an AspectJ thing or something else I wonder.

I think this just depends on when the NPE occurs - it'll likely fly up
the stack to the first person that can handle it (and someone must be
if it isn't coming out of the top and manifesting as a real failure).
If you have an NPE at just the wrong time I can imagine it killing
performance.  It could prevent a cache entry from being used or some
other work being repeated, something timing out which ordinarily
wouldn't (which is then dealt with in a different way).

Andy

> On 4/27/2012 7:56 PM, Andy Clement wrote:
>>
>> Hi,
>>
>> A few things that I can initially think of:
>>
>> - use jps/jstack to get the thread stacks of the JVM that you think is
>> hanging/going slow, is there an usual thread stack in there?
>>
>> - you don't have any synchronization in your aspect for accessing the
>> collections.  I feel like I've had problems in the past when modifying
>> a collection I'm iterating over.  To tell if it is the body of your
>> advice that is behaving badly, just comment it all out (use empty
>> advice) - that will tell you if the weaving is introducing the issue
>> or the logic in the advice body is introducing the issue.
>>
>> - The everything aspect looks ok.  I might do execution(public *
>> *(..)) just to reduce the output a bit, but it should be OK as you
>> have it.  You'd only get into issues here if you have types with loads
>> of methods, but then any problems would manifest as a weaving issue
>> (with the woven class getting too big for the JVM to handle).
>> Obviously instrumenting every little thing is going to have some
>> degree of performance impact.
>>
>> Andy
>>
>> On 27 April 2012 16:07, trhouse<trhouse@xxxxxxxxx>  wrote:
>>>
>>> Hi all,
>>>
>>> I am just trying to use AspectJ to get a handle on all the threads that
>>> an
>>> application runs. To start with, I just want to know how many there in
>>> how
>>> many ThreadGroups.
>>>
>>> I am using Loadtime Weaving to advise an admittedly large code base- a
>>> popular open source IDE. Yes, it's huge.
>>>
>>> What I am experiencing is the application "hangs" on start up without
>>> terminating and without seeming to progress or so it seems. By "hangs"
>>> all I
>>> mean is the application's splashscreen appears but the progress bar gets
>>> stuck after a while and doesn't move. For half an hour, at which time I
>>> quit
>>> the program.
>>>
>>> It DOES work as intended - it does give me the information I am seeking,
>>> but
>>> there just comes  a point when the output from this aspect is
>>> intermittent
>>> and the progress bar is not moving and I can't prove it's not in long
>>> many
>>> statement  infinite loop.
>>>
>>>
>>> So my question is, is there something special about advising
>>> Runnable.run()
>>> that is doomed to slow everything to a crawl or get caught in an infinite
>>> loop for some reason?
>>>
>>> The problem may be just  the sheer number of things I am trying to
>>> advise,
>>> because the code base is so large. The only reason I don't think that
>>> is
>>> using another aspect, I can advise all methods and the application
>>> successfully loads (then tells me I am out of memory and becomes
>>> uselessly
>>> slow). The "everything" aspect is just
>>>
>>>       pointcut captureAllMethods() : execution( * *(..));
>>>
>>>
>>> and then I print out the signature and source location in the before()
>>> statement of the aspect.
>>>
>>> I am sure you've all seen 1000 times before, but I included this aspect
>>> along with the thread aspect at the bottom of this question.
>>>
>>> Using this "everything" aspect also takes a long time but it does result
>>> ,
>>> after many minutes, in the application being launched.
>>>
>>> Oddly, when I apply BOTH aspects, the application I do get continuous
>>> output
>>> from the "everything" aspect. which means it's still running.
>>>
>>> In a slightly different version of the thread aspect, I make sure to
>>> !within
>>> the aspect itself, just in case I was entering an infinite loop with the
>>> aspect advising itself - something I don't see as even being possible
>>> given
>>> the particular aspect.
>>>
>>> I also do some System.out. printlns just to be sure that the thing is
>>> still
>>> alive, which it is.
>>>
>>> So I guess my other question is- have you been here before with really
>>> big
>>> code bases? Is this just something that's bound to be unusable and the
>>> fact
>>> that my  ( 64 bit AMD quadcore 8 gig RAM) computer runs for 45 minutes
>>> with
>>> no sign of further progress is not a surprise to anyone?
>>>
>>> Or is something else at work here?
>>>
>>> Any advise is appreciated.
>>>
>>>
>>>
>>>
>>>
>>>
>>> ---------------------------------------------------------------------------------------------------
>>> "Everything " aspect:
>>>
>>> ----------------------------------------------------------------------------------------------------
>>> package recipePackage;
>>>
>>> public aspect CaptureCallTargetRecipe
>>> {
>>>
>>>       pointcut captureAllMethods() : execution( * *(..))&&
>>> !within(CaptureCallTargetRecipe);
>>>
>>>
>>>       // Advice declaration
>>>       before() : captureAllMethods()
>>>       {
>>>
>>>          System.out.println(
>>>             "Signature: "
>>>                + thisJoinPoint.getStaticPart( ).getSignature( ));
>>>          System.out.println(
>>>             "Source Line: "
>>>                + thisJoinPoint.getStaticPart( ).getSourceLocation( ));
>>>          System.out.println();
>>>
>>>       }
>>> }
>>>
>>>
>>>
>>>
>>>
>>>  ---------------------------------------------------------------------------------------------------
>>> "Thread" aspect:
>>>
>>> ---------------------------------------------------------------------------------------------------
>>> package recipePackage;
>>>
>>> import java.util.ArrayList;
>>> import java.util.Iterator;
>>> import java.util.List;
>>>
>>> public aspect CaptureAllUniqueThreadsStartingRecipe
>>> {
>>>    static List<Thread>  threads = new ArrayList<Thread>(20);
>>>    static List<ThreadGroup>  threadGroups = new
>>> ArrayList<ThreadGroup>(20);
>>>    pointcut captureAllThreads(): execution(public void Runnable.run() ) ;
>>>
>>>
>>>    // Advice declaration
>>>    before(): captureAllThreads()
>>>            {
>>>                Thread thisThread = Thread.currentThread();
>>>                if (thisThread == lastThread)
>>>                {
>>>                    return;
>>>                }
>>>
>>>
>>>                lastThread = thisThread;
>>>
>>>                for (Iterator<Thread>  threadIterator =
>>> threads.iterator();
>>> threadIterator.hasNext(); )
>>>                {
>>>                    Thread nextThread = threadIterator.next();
>>>                    if (thisThread == nextThread)
>>>                    {
>>>                        threadFound = true;
>>>                        return;
>>>                    }
>>>                }
>>>
>>>                threads.add(thisThread);
>>>
>>>                for (Iterator<ThreadGroup>  threadGroupIterator =
>>> threadGroups.iterator(); threadGroupIterator.hasNext(); )
>>>                {
>>>                    ThreadGroup threadGroup = threadGroupIterator.next();
>>>                    if (Thread.currentThread().getThreadGroup() ==
>>> threadGroup)
>>>                    {
>>>                        threadGroupFound = true;
>>>                        break;
>>>                    }
>>>                }
>>>                {
>>>                    threadGroups.add(thisThread.getThreadGroup());
>>>                }
>>>
>>>
>>>                System.out.println("------------------- THREAD
>>> DISCOVERED--------------------");
>>>                System.out.println("New thread discovered: " +
>>> thisThread);
>>>                System.out.println("Thread List");
>>>                System.out.println("number Of Threads Created so far= " +
>>> threads.size());
>>>                System.out.println("number Of ThreadGroups Created far+ "
>>> +
>>> threadGroups.size());
>>>                System.out.println("Threads so far: ");
>>>
>>>                int i=0;
>>>                for (Iterator<Thread>  iterator = threads.iterator();
>>> iterator.hasNext(); )
>>>                {
>>>                    Thread nextThread = iterator.next();
>>>
>>>                    System.out.println();
>>>                    System.out.println("Thread Name : " +
>>> nextThread.getName());
>>>                    System.out.println("Alive? " + nextThread.isAlive());
>>>                    System.out.println("Daemon? " +
>>> nextThread.isDaemon());
>>>                    System.out.println("Thread Group? " +
>>> nextThread.getThreadGroup().getName());
>>>
>>>
>>>
>>>  System.out.println("------------------------------------------------------------");
>>>                }
>>>
>>>            }
>>>    public volatile boolean threadFound;
>>>    public volatile boolean threadGroupFound;
>>>    public Thread lastThread;
>>>    public Thread newThread;
>>> }
>>>
>>> _______________________________________________
>>> aspectj-users mailing list
>>> aspectj-users@xxxxxxxxxxx
>>> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>>
>> _______________________________________________
>> aspectj-users mailing list
>> aspectj-users@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>>
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top