| Summary: | 77% of CPU used doing nothing | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Pascal Rapicault <pascal> | ||||||||||||
| Component: | SWT | Assignee: | Silenio Quarti <Silenio_Quarti> | ||||||||||||
| Status: | RESOLVED FIXED | QA Contact: | |||||||||||||
| Severity: | critical | ||||||||||||||
| Priority: | P3 | CC: | eclipse.felipe, markus.kell.r, remy.suen, Silenio_Quarti, skovatch | ||||||||||||
| Version: | 3.6 | Flags: | skovatch:
review+
|
||||||||||||
| Target Milestone: | 3.6 RC1 | ||||||||||||||
| Hardware: | Macintosh | ||||||||||||||
| OS: | Mac OS X | ||||||||||||||
| Whiteboard: | |||||||||||||||
| Attachments: |
|
||||||||||||||
I have noticed that if I close the Java perspective the CPU consumption goes down to a more normal 5% Created attachment 167852 [details]
Another log, before I close the JDT perspective
Created attachment 167853 [details]
After I close the JDT perspective
Scott, we need to try to reproduce this problem. Note that one of the stacks is running the new Link.computeSize() code. Pascal, would you be able to try the 32 bit and see if this problem can be reproduced with it? When you get this to happen again, go to Terminal.app and type 'sample 2 20 <eclipse's PID>' and attach the stack trace. The calculation of the size of Link is suspicious, since I just changed Link.computeSize recently. As I recall, NSLayoutManagers are expensive to create and destroy since they check in with the notification manager, and are meant to be reused. Scott, do you prefer that I keep running the 64 bits version in order to gather the sample, or do you prefer that I first try the 32 bits version. As long as you can get to happen, 32 vs. 64 bits shouldn't matter. If you were seeing memory pressure I would expect it to be easier to reproduce with the 64-bit version. Created attachment 167863 [details]
Possible patch
Based on similar change in TextLayout. Cache a NSLayoutManager and associated classes for doing size calculations.
The main thread is in DetailedProgressViewer, which is e.g. used in the Progress view. I guess you had the Progress view open in the JDT perspective (and only in that perspective), so when you closed it, the problem went away. Things that could ease your life without a patch: - close the Progress view (in all perspectives) - if your Progress view shows sleeping and system jobs, disable this (in the view menu > Preferences) Scott, can you reproduce the problem ? Can you verify that your changes fix the problem ? Note that Text#computeSize() has the same code. (In reply to comment #10) > Scott, can you reproduce the problem ? > > Can you verify that your changes fix the problem ? Not yet, no. That's why I labelled it a possible fix. Based on the stack traces Pascal posted and the history of NSLayoutManagers in the Cocoa port, though, it's a strong suspect. When the latest I-build finishes I will update and use Markus' suggestion to see if that reproduces it for me. > Note that Text#computeSize() has the same code. Good point. I suspect we don't see enough multi-line Text's in Eclipse to trigger this. (In reply to comment #8) > Created an attachment (id=167863) [details] > Possible patch > Based on similar change in TextLayout. Cache a NSLayoutManager and associated > classes for doing size calculations. If NSLayoutManager is really the problem, we should probably have a shared instance in display to perform compute size for Text and Link. Scott, are you able to reproduce the problem in the latest build? (In reply to comment #12) > If NSLayoutManager is really the problem, we should probably have a shared > instance in display to perform compute size for Text and Link. I remember you and Kevin looked at this once... wasn't it something to do with NSNotificationManager? I'm basing my changes on the info in the attached dumps and the history. I'm not suggesting this is THE fix -- not without more evidence. > Scott, are you able to reproduce the problem in the latest build? No, I haven't been able to reproduce it. I'm running the 32-bit version, though. I should try 64-bit for a while. The larger heap and memory conditions might be enough to trigger it. Yes, the problem Kevin and I saw was in the NSNotificationCenter. NSLayoutManager adds and removes observers to the center. When the layout was released, some how removing the observer from the notification became painfully slow. Pascal, when did you start seeing this problem? Last week or even before that. There are changes made in GC.drawText() and GC.textExtents() around mid April for bug#290373 that could cause of this problem as well. We stop using Core text in favor of NSLayoutManager. I started seeing these problems a while back, it is the probably the same pb I had emaild you about late April We figured this one. The problem is that Link is leaking the NSScrollView, which leaks a NSTextView, which leaks a NSLayoutManager, which leaves a observer in the notification center, which causes everything to go slow at some point. I will attach a snippet the reproduces the problem and a fix. Test code. Note that at some point the loop iteration goes slower.
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.*;
public class MainSSQ {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
for (int i = 0; i < 100000; i++) {
long time= System.currentTimeMillis();
// Text control = new Text(shell, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
Link control = new Link(shell, SWT.NONE);
// control.setText("XXX");
for (int j = 0; j < 10; j++) {
control.computeSize(-1, -1);
// GC gc = new GC(shell);
// gc.getFontMetrics();
// gc.dispose();
}
control.dispose();
System.out.println("time=" + (System.currentTimeMillis() - time));
}
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Created attachment 168191 [details]
fix
Ouch. Yes, that would do it. Looks good. Actually, after running your test I think we need both patches. Even with the patch the time still goes up at a pretty steady rate, topping out at 60+ ms, but with both in place it levels out for me at about 21 ms. It does not go up for me. What it is different? You are running on Snow Leopard? God. I need to read what I type... It does not go up for me. What is different between my setup and yours? Are you running on Snow Leopard? Do you have a test case that you want me to try on my machine (I would need a compiled version of SWT)? (In reply to comment #23) > It does not go up for me. What is different between my setup and yours? Are you > running on Snow Leopard? I am on Snow Leopard, and I'm running 32-bit. After about a minute the time reported is around 50. It fluctuates but it keeps going up. (In reply to comment #25) > (In reply to comment #23) > > > It does not go up for me. What is different between my setup and yours? Are you > > running on Snow Leopard? > > I am on Snow Leopard, and I'm running 32-bit. After about a minute the time > reported is around 50. It fluctuates but it keeps going up. I reboot to Snow Leopard and I can confirm that the rate goes up in this version. The time goes up in Snow Leopard because the testcase does not run an event loop. There is probably some change in cocoa that needs to event loop to do some clean up. I changed the test code to flush events in between iterations and the time does not go up anymore. I believe this is not a problem because normally the application is running the event loop.
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.*;
public class MainSSQ {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
// new MessageBox(shell, SWT.NONE).open();
for (int i = 0; i < 10000; i++) {
long time= System.currentTimeMillis();
// Text control = new Text(shell, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
Link control = new Link(shell, SWT.NONE);
// control.setText("XXX");
for (int j = 0; j < 10; j++) {
control.computeSize(-1, -1);
// GC gc = new GC(shell);
// gc.getFontMetrics();
// gc.dispose();
}
control.dispose();
while (display.readAndDispatch());
System.out.println("time=" + (System.currentTimeMillis() - time));
}
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
// try {
// System.in.read();
// } catch (Throwable e) {}
}
}
Pascal, I believe your bug is fixed with the patch I attached, but I cannot confirm that. This is the only change are going to put in for RC1. I was going to attach a jar for you to try out, but it is too big. If you would like I can send it to you. Otherwise, please try tomorrow's i-build. Reopen if the bug is not fixed. Fixed > 20100512. I can wait. Thx for the quick turnaorund. *** Bug 311327 has been marked as a duplicate of this bug. *** |
Created attachment 167848 [details] VM dump when the CPU is pegged at 77% In the last few weeks, I have been observing some really weird problems on the cocoa 64bits where Eclipse uses around 80% of my CPU while I'm not using it. I just have eclipse (with focus) on the java perspective with all the editors closed. When I try to use this instance, it is basically unusable as it is way to slow to type or do anything significant. At first I thought this was caused by additional plugins, but for the attached dump I'm using stock eclipse SDK I20100509-0800. The only way I found to get rid of this problem is to either restart eclipse.