Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 43758

Summary: [Jobs] Should run progress views and status lines with one update job
Product: [Eclipse Project] Platform Reporter: Jerome Lanneluc <jerome_lanneluc>
Component: UIAssignee: Tod Creasey <Tod_Creasey>
Status: RESOLVED INVALID QA Contact:
Severity: normal    
Priority: P3 CC: john.arthorne
Version: 3.0   
Target Milestone: ---   
Hardware: PC   
OS: Windows 2000   
Whiteboard:
Bug Depends on: 43841    
Bug Blocks:    

Description Jerome Lanneluc CLA 2003-09-26 12:21:26 EDT
Build 20030925

If the Progress view is visible and theres's a lot of background activity (e.g. 
a long autobuild, or a CVS checkout), the whole Workbench freezes while the 
Progress view is updating.

Closing the Progress view makes the UI more responsive.
Comment 1 Tod Creasey CLA 2003-09-29 12:29:18 EDT
This is because the progress view updates every 100 ms and there will be a lot 
of updates if a lot of work is going on. These updates should be slowed down 
if the system is very busy.

John is there a decent way to make this determination?
Comment 2 John Arthorne CLA 2003-09-29 12:43:04 EDT
We've had a few reports of responsiveness problems in the latest build, so I'm
going to do some much need profiling this afternoon to see what I can turn up.
I'd like to understand where the time is going before we do further tweaking.
Comment 3 Tod Creasey CLA 2003-09-29 14:41:36 EDT
I have written a test that runs a seperate job for each file or directory 
entry in your Eclipse install - it usually hits close to 500 posted jobs at a 
time.

The presence of the ProgressView appears to make no difference (in fact it was 
faster when the view was open but I think this doesn't really mean anything).

Jerome can you give me an idea of the types of things going on in your 
workbench at a given time? I am not sure that we make that much difference but 
if there are expensive UI operations going on the updates could be a factor in 
process switching.
Comment 4 Tod Creasey CLA 2003-09-29 16:29:41 EDT
I have found a place where I was synching during an update to the viewer in 
the progress view and I have refactored the synch to finish before the update 
occurs. This will be in build >20030929 but I am going to leave this PR open 
as I expect we may find more inprovements.
Comment 5 John Arthorne CLA 2003-09-29 17:21:47 EDT
I've done some profiling, and I haven't found anything in particular about the
progress view that is bogging the system down. During a background task that
reported 1,000,000 units of progress, the system was responsive and the progress
view updated quickly.

One thing to consider: the scheduling delay for the "updating progress" job is
currently 100ms... this is the main thing that makes it responsive right now. 
I.e., on the job that reported 1,000,000 units of progress, the progress manager
tried to schedule 1,000,000 UI jobs to update the progress view, but only a very
small number actually got scheduled (one every 100ms).  This is a good thing,
but we could consider upping the 100ms delay to something greater, such as 250ms
or even 500ms to get even more batching.
Comment 6 John Arthorne CLA 2003-09-29 17:51:19 EDT
This is not the cause of the problem, but I thought it worth point out:
profiling a job that just reports progress in a tight loop shows the largest
chunk of time is spent in JobProgressManager.refresh (I think this has been
renamed to ProgressManager in HEAD).  Most of the time is spent in the overhead
of acquiring the object monitor (about 10% of total thread time).

In core, we use the "copy on write" pattern for situations like this.  Assuming
that modifying the set of listeners is relatively rare, but traversal is very
common, you can do the following:

- On traversal, obtain a pointer to the array and iterate over that:

IJobProgressListener[] temp = this.listeners;
for (int i = 0; i < temp; i++)
   temp[i].refresh(...)

- On modification, synchronize and copy the entire array:

synchronized (listeners) {
  IJobProgressListener[] temp = this.listeners;
  IJobProgressListener[] newList = new IJobProgressListener[temp.length+1];
  System.arraycopy(temp, 0, newList, 0, temp.length);
  newList[temp.length] = newListener;
  this.listeners = newList; //atomic assignment
}

- the synch block when modifying the set of listeners is just to prevent
multiple concurrent changes to the listener list.  It doesn't prevent concurrent
reads.

This is a fairly advanced optimization so I'm not sure if it's worth it at this
point, but something to keep in mind.
Comment 7 Jerome Lanneluc CLA 2003-09-30 06:30:12 EDT
Tod, I have autobuild turned on, and all I do is incremental builds. If an 
incremental build takes a long time (e.g. change the value of a constant), 
while the builder compiles all the dependent of the changed file, the progress 
view updates with each package that is being recompiled. And while it is 
updating, I cannot even move the workbench windows (note that I have several 
windows open if it makes any difference). Also this is on Win2000.

I'll try today's build and let you know if your change improves things.
Comment 8 Tod Creasey CLA 2003-09-30 08:46:15 EDT
This was where my idea about being able to determine relative busyness of the 
job manager came in - jobs with DECORATE priority could have thier service 
time increased when loads are heavy.

I now get the list of updates in the synch block but do the updates outside of 
it - I would be interested in seeing the difference with todays build.
Comment 9 Tod Creasey CLA 2003-09-30 16:00:58 EDT
I have just checked in 20030930 and the responsiveness with the ProgressView 
appears to be fine in your case.

I am going to close this PR - please reopen if you find a problem use case.
Comment 10 Jerome Lanneluc CLA 2003-10-01 05:09:55 EDT
Unfortunately, I can still see the problem in I20030930. I'll reopen the bug as 
soon as I find steps to reproduce.
Comment 11 John Arthorne CLA 2003-10-01 13:22:39 EDT
Jerome, how many workbench windows do you typically have open?  I wonder if it
only really starts to thrash when there are many workbench windows.

Tod: is there a separate job to update the status line/progress view of each
window?  I wonder if this is the problem: five windows with two jobs per window
(one status line and one progress view) is ten asyncExecs for each unit of
progress.  I can imagine this bringing the UI thread to its knees.  Ideally a
single job could update all status lines...
Comment 12 Tod Creasey CLA 2003-10-01 13:40:23 EDT
Yes they are currently seperate jobs right now mostly because the progress 
view gets updated much more frequently. I want to avoid computation inside the 
job or worse yet in a synched part of the job - melding them together would 
make this much more prone to freezing.
Comment 13 John Arthorne CLA 2003-10-01 13:50:33 EDT
Ok, the status line and progress view can't be updated together then.  How about
a single job for the progress view, and a single job for all status line
updates? This would be similar to our solution for the animation loop, where you
collapsed one job per window down into a single job for all windows.
Comment 14 Tod Creasey CLA 2003-10-01 14:02:41 EDT
Thats a good idea. Jerome how many windows do you run in
Comment 15 Jerome Lanneluc CLA 2003-10-01 15:47:09 EDT
I usually have 3 to 5 windows open.
Comment 16 Tod Creasey CLA 2003-10-06 11:47:32 EDT
The fix for running the progress view with one updater is in build >20031006
Comment 17 Tod Creasey CLA 2003-11-19 13:36:58 EST
Upgrading to P3 as there is now a problem where the status line is getting 
updated but the progress view isn't - we need to keep the timing consistent.

What might be the best solution is to add the 3 UI based listeners (status, 
progress and indicator) to a single update job.
Comment 18 Tod Creasey CLA 2004-02-11 17:22:15 EST
Status line no longer shows updates.