Bug 117740 - Parameter names completion should be done asynchronoulsy
Summary: Parameter names completion should be done asynchronoulsy
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 critical (vote)
Target Milestone: 3.2 M4   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords: performance
: 118947 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-11-23 11:27 EST by Olivier Thomann CLA
Modified: 2005-12-13 05:40 EST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Olivier Thomann CLA 2005-11-23 11:27:39 EST
We might need a mecanism to retrieve the parameter names from the javadoc asynchronously. It can take a pretty long time on a slow network to retrieve it.
This might require some API from JDT/Core, but I think it might be worth investigating it first on the UI level.
Comment 1 Pascal Rapicault CLA 2005-11-23 14:42:07 EST
it seems that the biggest performance hit I see is on the first time. Maybe the opening of an Http URL causes the loading of new classes.
Comment 2 Dani Megert CLA 2005-11-24 05:04:42 EST
I assume this happens with the new Javadoc support for parameter hints. Making this asynchronous would be bad for the typing experience. If performance is a problem then we might have to give users the option to disable this.
Comment 3 Olivier Thomann CLA 2005-11-24 08:57:28 EST
The problem is mostly that the performance depends a lot of the network.
I would suggest an option in the code assist preference to explicitly allow the search inside javadoc. This will however require a new API on the JDT/Core side.
Comment 4 Pascal Rapicault CLA 2005-11-24 09:05:21 EST
Having an option is nice, but still when it is turned on you can get a pretty long  latency (try in the last I build to do completion on equals() and have the javadoc remote (which I believe is the default)) which by the way freezes the whole UI.

The idea of the asynchronous call was: the ui makes a call to get the parameters. It receives an array of objects. Each object wrappers the raw parameter name and a future object on the javadoc. This would allow the UI to display the javadoc if it is available quickly enough, or to default to the parameter name. Note that this approach might have the problem where returning the javadoc would always be slower than getting the raw paremeter and cause the javadoc to never be displayed.
Comment 5 Dani Megert CLA 2005-11-24 09:51:33 EST
If it takes long, it probably also affects code assist because there the parameter names are also filled in.
Comment 6 Pascal Rapicault CLA 2005-11-24 10:19:11 EST
Yep that's where I got burnt in the first place.
Comment 7 Dani Megert CLA 2005-11-24 10:25:09 EST
This would mean asynchronous code assist api as well.

Another solution would be a timeout. If it takes longer than that JDT Core provides the raw names.
Comment 8 Dani Megert CLA 2005-12-02 02:40:56 EST
The new support can cause major damage in code assist.

Test Case:
1. make sure Javadoc location is set to http://java.sun.com/j2se/1.4.2/docs/api/
2. no source attached
3. in a CU type: String s;s.<code assist>
==> takes up to 45s and the UI is blocked
Comment 9 Dani Megert CLA 2005-12-02 02:59:45 EST
*** Bug 118947 has been marked as a duplicate of this bug. ***
Comment 10 Dani Megert CLA 2005-12-02 03:00:56 EST
Increasing severity since this happens to all users that setup their workspace with a JRE (no source).
Comment 11 Olivier Thomann CLA 2005-12-02 08:44:13 EST
(In reply to comment #8)
> Test Case:
> 1. make sure Javadoc location is set to
> http://java.sun.com/j2se/1.4.2/docs/api/
> 2. no source attached
> 3. in a CU type: String s;s.<code assist>
> ==> takes up to 45s and the UI is blocked
On my machine, this doesn't take 45s. Maybe one or two. No more.
So what do you suggest? Should we remove that support?
The lag seems to be related to the network. One solution is to get the doc locally instead of a remote location.
Comment 12 Dani Megert CLA 2005-12-02 09:20:46 EST
Yes, it's for sure the network access. Did you make sure that there's no attached source?

When I open the Javadoc via browser it's also around 1s. But via Eclipse code assist for String s; s.<...> really takes 45s - no joke.

One thing I've noticed when looking at the code is that it loads the same information many times i.e. it reads
  docUrlValue= "http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html"
from the net n times instead of just once.
Comment 13 Pascal Rapicault CLA 2005-12-02 09:29:33 EST
Even we were going only once to the server, it should still be done in the background since you may go over dial-up or someother slow connection.

Note that I think the support is really cool though :)
Comment 14 Olivier Thomann CLA 2005-12-02 09:56:58 EST
(In reply to comment #12)
> Yes, it's for sure the network access. Did you make sure that there's no
> attached source?
yes. I removed the source attachment.

> One thing I've noticed when looking at the code is that it loads the same
> information many times i.e. it reads
>   docUrlValue= "http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html"
> from the net n times instead of just once.
What do you mean? I get the javadoc contents only once per java element. Do you have a pointer where I do it more than once?

Comment 15 Dani Megert CLA 2005-12-02 10:02:32 EST
Doing this in the background might be hard, especially with the new code completion participants - J Core guys tell me if I'm wrong about that.

I think adding a timeout is the best solution since you might want to use the feature at home where it's fast but not in the office where it's slow and you don't want to adjust the preference every time.
Comment 16 Dani Megert CLA 2005-12-02 10:12:01 EST
Code assist collects the parameters for each entry/member and for each such call it downloads String.html.
Comment 17 Olivier Thomann CLA 2005-12-02 10:21:23 EST
Then maybe we can try some caching of the javadoc contents.
It might increase the memory, but at least only one call would be done for each type.
Comment 18 Susan McCourt CLA 2005-12-02 12:59:28 EST
for what it's worth - this performance penalty is orders of magnitude harsher than the network would warrant.  I just tried to get method signatures for String and it took 80 seconds.  Completing methods for "System" is taking around 20 seconds.  I'm on a DSL connection, using wireless network showing 11 Mbps speed.  So while it's not a blazingly fast network, it's certainly not a slow dial-up connection, and accessing complex web pages, CVS operations, etc., are all of quite acceptable speed.  In other words, I'm not a user who is "used to a slow network," my network performs fine everywhere else.
Comment 19 Olivier Thomann CLA 2005-12-02 13:37:30 EST
Then I propose to disable the functionality for now.
Comment 20 Dani Megert CLA 2005-12-04 13:20:18 EST
Can't you run through a profiler? Something must be really wrong here: I also have a DSL (2400Mbs) connection and accessing the Javadoc via browser is instant (around 1s) but code assist on String s;s. take s up to 2 minutes.
Comment 21 Olivier Thomann CLA 2005-12-05 10:32:34 EST
I released a patch that is caching the javadoc contents inside the perProjectInfo. This is reset when the classpath is modified. I got much better performance doing this.
Right now I am only caching the doc for the type and I use this doc to retrieve the part relative to the type/field/method.
Let me know if this is good enough.
I leave this PR open till I get feedback.
Comment 22 Olivier Thomann CLA 2005-12-05 10:40:01 EST
If someone could try using HEAD contents of JDT/Core, it would be great.
Thanks.
Comment 23 Susan McCourt CLA 2005-12-05 10:55:17 EST
Before loading latest from head, getting the signatures for String took 110 seconds.  After loading the latest, it takes around 3 seconds.
Comment 24 Olivier Thomann CLA 2005-12-05 10:57:49 EST
And it should be even faster for the second completion.
Comment 25 Dani Megert CLA 2005-12-05 11:37:01 EST
I've tested with JCore from head: good progress, specially on the second an subsequent invocations! Also the first one is much faster (down to about 3-4s) but I think while typing this might still not be good enough. I did not look deep into the code but I think the param info is collected per proposal. Couldn't you add a limit and if this is exceeded simply use raw names?
Comment 26 Susan McCourt CLA 2005-12-05 12:04:29 EST
I also observed that it was much faster on subsequent completions.  I agree with Dani's comments.  The improvement is significant, but it would be nice if the first invocation were faster.
Comment 27 Olivier Thomann CLA 2005-12-05 12:44:40 EST
I will disable the completion of parameter names from javadoc as long as we cannot improve the speed.
Comment 28 Olivier Thomann CLA 2005-12-05 13:13:30 EST
I checked the time spent to retrieve the javadoc contents.
First call:

Time spent 1853ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 621ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html

Second call after closing/reopening the project
Time spent 821ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 110ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html

Third call after closing/reopening the project
Time spent 811ms for 
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 120ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html

It seems that the first call is much slower than the other ones. I don't really see a way to cut down this time. I don't control it.

Other times:
Time spent 1942ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 101ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 821ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 101ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 812ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 110ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 821ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 120ms for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html

In the best case, there is about 1s lost to retrieve the contents of the url. In the worse case it is almost 3s.

Should we do it for remote locations? I'll get some numbers with a local doc.
Comment 29 Olivier Thomann CLA 2005-12-05 13:38:20 EST
Detailed numbers:
- opening the connection
- getting the stream
- reading the stream

First try:
Time spent 0ms for opening connection for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 1242ms for getting stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 731ms for reading stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html

Next tries (closing/reopening the project between each try):

Time spent 0ms for opening connection for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 101ms for getting stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 10ms for reading stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 0ms for opening connection for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 170ms for getting stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 631ms for reading stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 0ms for opening connection for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 90ms for getting stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 20ms for reading stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 0ms for opening connection for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 181ms for getting stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 631ms for reading stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html
Time spent 0ms for opening connection for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 100ms for getting stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Time spent 20ms for reading stream for http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html
Comment 30 Dani Megert CLA 2005-12-06 02:56:15 EST
Can you test how the performance is when the Javadoc is local? I'd expect this to be no problem. If so, you could add a preference which allows to control getting parameter names from non-local Javadoc. However, as said before a timeout based solution would be much nicer: code assist could spawn a new thread to get the parameter info and if it does not complete before the timeout simply continue with the original thread using he raw name.
Comment 31 Jerome Lanneluc CLA 2005-12-06 04:59:08 EST
I would prefer a preference rather than a timeout. With a timeout, you get inconsistent results. It is quite disturbing to sometimes get the parameter names, sometimes not.
Comment 32 Dani Megert CLA 2005-12-06 05:02:27 EST
The timeout would be a preference as well. The idea is that you do not have to change the preference when working at different locations.
Comment 33 Jerome Lanneluc CLA 2005-12-06 05:08:05 EST
I see. A timeout of 0 would disable the feature, and an infinite timeout would force codeassist to always wait for the javadoc. I like that.
Comment 34 Dani Megert CLA 2005-12-06 05:11:01 EST
Not that this should *not* be coded into the method that gets the Javadoc but only for getting the parameters since the hover and the Javadoc view are using different threads to compute the info and hence the UI is not blocked.
Comment 35 Tom Hofmann CLA 2005-12-06 05:14:40 EST
IMO, assist is so performance sensitive that we can never show parameter names unless they are locally cached when content assist is invoked.

I am curious whether caching the javadoc locally is even enough - parsing the javadoc source for all types along the type hierarchy before showing the content assist popup may already be too expensive.

The correct solution would be to show parameter names when they are available (for example cached from a previous display of the hover help...), and use raw / generated names otherwise.
Comment 36 Olivier Thomann CLA 2005-12-06 09:06:57 EST
It is much faster when the doc is local.

Time spent 51ms for reading stream for jar:file:/D:/Downloads/jdk-1_5_0-doc.zip!/docs/api/java/lang/String.html
Time spent 30ms for reading stream for jar:file:/D:/Downloads/jdk-1_5_0-doc.zip!/docs/api/java/lang/Object.html
Time spent 20ms for reading stream for jar:file:/D:/Downloads/jdk-1_5_0-doc.zip!/docs/api/java/lang/String.html
Time spent 511ms for reading stream for jar:file:/D:/Downloads/jdk-1_5_0-doc.zip!/docs/api/java/lang/Object.html

So we might want to implement a timeout solution. This might require to add new API to get the parameter names since the actual API has no idea of time out.
Comment 37 Olivier Thomann CLA 2005-12-06 15:42:00 EST
Here is what I can propose.
Two new options:
1) to set the timeout for getParameterNames()
2) a option to know if parameter names should be retrieved for remote javadoc

If option (2) is true and (1) has a short time-out, then the first call will spawn a new thread that will retrieve the javadoc asynchronously. If it completes before the timeout, the actual parameter names are returned. If not, the default names (arg0, arg1, ...) are returned.
All the other calls will return the default names as long as the thread has not completed. Once the javadoc is retrieved, it is cached in a LRU cache (size 5). We might increase this value if we end up flushing the cache too many times.
So another code assist a second or so later will actually return the right values.

How does this sound?
Comment 38 Susan McCourt CLA 2005-12-06 16:30:00 EST
Is option (2) really necessary in light of option (1)?

If the default timeout is short, then you get the feature when it's reasonable but can remain ignorant about the feature's existence and the driving timeout preference.  Only those users who notice a difference in the behavior across environments will need to set the prefs.
Comment 39 Olivier Thomann CLA 2005-12-06 21:44:14 EST
I would say yes, but this is debatable.
Option (1) would be used only if option (2) is true. One my machine if the timeout is lower than 1s, I would never get the javadoc in time. It takes between 1 and 2s to retrieve the javadoc on my machine. To be honest, I have no idea why it takes so long to get the input stream on the url connection on the first call.
If someone knows a way to retrieve efficiently the contents of a url, I am very interested. I tried to use some code from the commons-http apache package and I got time also between 1 and 2s.
Comment 40 Dani Megert CLA 2005-12-07 03:28:19 EST
As Susan I'd vote to do just 1). We can add 2) if we see that 1) isn't enought.
Comment 41 Tom Hofmann CLA 2005-12-07 04:39:51 EST
(In reply to comment #40)
> As Susan I'd vote to do just 1). We can add 2) if we see that 1) isn't enought.

+1
Comment 42 Olivier Thomann CLA 2005-12-07 09:47:04 EST
ok, so let's introduce only a timeout for now.
I'll release a patch shortly and you will let me know if this solves this issue.
Comment 43 Olivier Thomann CLA 2005-12-07 10:13:13 EST
Would this option name be good enough CODEASSIST_TIMEOUT_FOR_PARAMETER_NAMES?

It would be defined on the JavaCore class and can be retrieved through the project's option.
Comment 44 Olivier Thomann CLA 2005-12-07 11:47:29 EST
I released a patch that does the computation asynchronously. Daniel, please let me know if this solves this problem.
I put 150ms as the default value for the timeout. This might change when we get more testing. With a local doc, I am between 50 and 60ms. So we might want to reduce the default below 100ms.
I leave this bug open for now.
Comment 45 Olivier Thomann CLA 2005-12-08 11:33:53 EST
Asynchronous support is in place.
Some time-out support might be added for the code assist.
Fixed and released in HEAD.
Daniel, please annotate the PR once you check that your test case with JFrame is acceptable.
Comment 46 Frederic Fusier CLA 2005-12-13 05:40:09 EST
Field name is in fact CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC.
Verified for 3.2 M4 with build I20051213-0010