Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 258177 - [Decorators] DecorationScheduler calling wakeUp()/schedule() on decorationJob too often
Summary: [Decorators] DecorationScheduler calling wakeUp()/schedule() on decorationJob...
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.4.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.5 M7   Edit
Assignee: Kevin McGuire CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-12-09 15:43 EST by Randall Theobald CLA
Modified: 2009-06-03 13:33 EDT (History)
4 users (show)

See Also:


Attachments
PoC patch (1.15 KB, patch)
2008-12-09 15:43 EST, Randall Theobald CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Randall Theobald CLA 2008-12-09 15:43:54 EST
Created attachment 119963 [details]
PoC patch

Build ID: 3.4.1.M20080827-0800a

Steps To Reproduce:
I am a performance analyst for an adopting product. During analysis of our forthcoming release (based on Eclipse 3.4.1), we observed a lot of stress on the locks used in the eclipse.jobs plugin. One source of this stress is coming from the 

    org.eclipse.ui.internal.decorators.DecorationScheduler

class, which is calling wakeUp() and schedule() on its 'decorationJob' thousands of times during a build of a medium-sized workspace.

Since this is UI-specific, there should be a check for when the last time the wakeUp() request was made, and only make the request if enough time has elapsed (such as 100 ms). This will ease the stress on the jobs locks slightly.

This follows a general pattern that we are seeing, that updates to the UI are made much too quickly, using a lot of system resources. In UI-specific plugins, care should always be taken to not do things too often, thus avoiding unnecessary processing.

I have attached a proof-of-concept patch (on R3_4_maintenance) that reduces the number of times these methods are called dramatically for my workload (e.g. from > 17k times to < 1k times).
Comment 1 Boris Bokowski CLA 2008-12-11 12:33:21 EST
Randall, how much effect does your patch have on the elapsed time of the build?
Comment 2 Randall Theobald CLA 2008-12-11 16:19:50 EST
I have measured an average improvement of about 1 sec (slightly over 1%) for subsequent builds. 

However, I failed to mention that I ran into this when investigating high variability in the amount of time getting Java locks. I opened this bug to mostly help with the variability (by reducing some of the strain on the hot locks).

Comment 3 John Arthorne CLA 2008-12-12 10:15:21 EST
I don't actually see why wakeUp is called at all here. There are two ways a job can get into the sleeping state:

 1) Job.sleep() is called. In this case there must be a future call to wakeUp() or it will sleep forever
 2) Job.schedule() is called, and the job scheduler decides to let the job sleep for awhile (it does this for jobs with DECORATE priority when the system is under load)

In DecorationScheduler, 1) never happens as far as I can see, which means the job is sleeping because schedule() has been called. In this case wakeUp() will just remove the job from the sleep queue, and then re-insert it, possibly in a slightly different position. I can see his has overhead because it's removing an item from a linked list and then re-inserting it, which are both O(N) operations. 

I would suggest removing the wakeUp() call entirely and just leave the schedule() call there. schedule() is relatively quick when a job is already in the sleep or wait queues. I would suggest trying this out in 3.5 for awhile before back-porting to a maintenance release though.

A more conservative optimization is to avoid calling schedule() in the case wakeUp() has been called. Calling schedule() right after wakeUp() is guaranteed to have no effect. I.e., change this:

	if (decorationJob.getState() == Job.SLEEPING) {
		decorationJob.wakeUp();
	}
	decorationJob.schedule();


To this:

	if (decorationJob.getState() == Job.SLEEPING) {
		decorationJob.wakeUp();
	} else {
		decorationJob.schedule();
	}
Comment 4 Boris Bokowski CLA 2008-12-12 10:31:52 EST
Hi Kevin, I just set the milestone to M5 thinking the bug was assigned to me. Sorry! Feel free to undo that or change to a different target.
Comment 5 Kevin McGuire CLA 2009-04-24 10:03:36 EDT
(In reply to comment #3)
> I don't actually see why wakeUp is called at all here.

> I would suggest removing the wakeUp() call entirely and just leave the
> schedule() call there. schedule() is relatively quick when a job is already in
> the sleep or wait queues. 

Thanks John.

I've tried as you suggested and it seems to perform just fine, and still quite perky - e.g. expanding trees of projects brought in from CVS, the CVS info appears just as fast (subjectively), even with builds running.  I've noticed some pauses but also with the old code, plus we have the UI job in the mix to do the actual painting, so not sure this change is a factor.

I assume the code was as it was because of concern that the job needed to be "kicked" when new work was needed to be performed.  But as you indicated, schedule() along is enough.
Comment 6 Kevin McGuire CLA 2009-04-24 10:54:00 EDT
Released to HEAD
Comment 7 Kevin McGuire CLA 2009-04-28 21:30:58 EDT
Verified in 0428-0100 that the code is released and that decorators still work in a timely fashion.
Comment 8 John Arthorne CLA 2009-06-03 13:29:19 EDT
Comment on attachment 119963 [details]
PoC patch

Removing iplog+ flag, this patch wasn't released.