RE: Jde-complete performance

"Nascif Abousalh-Neto" <[email protected]>
Newsgroups gmane.emacs.jdee
Message-ID <[email protected]>
Hi Suraj,
 
Really nice to see you keep making improvements to jde-usages. I guess it is about time that it becomes elevated from plugin to base code status :-)
 
Do you have any ball-park comparisons on performance improvements by using one data structure over the other for the functionality below?
 
Thanks,
  Nascif

________________________________

From: Suraj Acharya [mailto:[email protected]] 
Sent: Tuesday, April 11, 2006 11:42 AM
To: Nascif Abousalh-Neto
Cc: [email protected]
Subject: Re: Jde-complete performance


Hi Nascif,

CVS jde-usages has two exprimental features

1)  an implementation of getClassInfo which uses the jde-usages data structures :
(defalias 'jde-complete-invoke-get-class-info 'jde-usages-complete-invoke-get-class-info) 

2) A slightly reworked jde-parse-eval-type-of which changes the order in which in tests for the type of the input. The main change is that it defers the expensive  call to jde-parse-get-qualified-name as long as possible if the suspected class name does not match the usual class name convention, eg "FooBarBaz". 
(defalias 'jde-parse-eval-type-of 'jde-usages-parse-eval-type-of)

There are also some other functions that replace JDEE java code by using the jde-usages structures:

(defalias 'jde-parse-get-qualified-name 'jde-usages-parse-get-qualified-name) 
(defalias 'jde-parse-class-exists 'jde-usages-parse-class-exists)


These features are exprimental because I don't have any regression tests yet for them, and have not done any exhaustive tests to look for differences from the jde behaviour, however I use emacs with these features turned on and fix bugs as I find them, so they're quite stable and usable. 

See the CVS release notes and change log under usages/web.

Suraj


On 4/11/06, Nascif Abousalh-Neto < [email protected] <mailto:[email protected]> > wrote: 

	Hi all,
	
	I am aware that JDEE has an "intellisync" feature implemented in the jde-complete family of methods. To be honest I don't use it much for two reasons: 1) it doesn't always work and 2) it is very, very slow. It usually takes on the order of 13-15 seconds for it to return, and in the mean time it locks everything in Emacs. Even if it is just a first time impact since the class information is cached, still is quite a long time to wait. 
	
	I looked at the code, and I found this interesting bit:
	
	(defun jde-complete-get-classinfo (name &optional access-level)
	
	...
	
	  (let ((class-info (jde-complete-get-from-cache name))
	        public-methods protected-methods private-methods 
	        package-methods)
	    (when (not class-info)
	      ;;Getting public class info
	      (setq public-methods
	            (jde-complete-invoke-get-class-info
	             name jde-complete-public))
	
	      ;;Getting protected class info
	      (setq protected-methods
	            (jde-complete-invoke-get-class-info
	             name jde-complete-protected))
	
	      ;;Getting package class info
	      (setq package-methods 
	            (jde-complete-invoke-get-class-info
	             name jde-complete-package))
	
	      ;;Getting private class info
	      (setq private-methods
	            (jde-complete-invoke-get-class-info
	             name jde-complete-private))
	      (setq class-info (append public-methods
	                               protected-methods
	                               package-methods
	                               private-methods)) 
	
	The method jde-complete-invoke-get-class-info is called four times. On each call it uses the BeanShell to invoke the following Java method in the JDE utility class Completion.java:
	
	  public static void getClassInfo(String className, int level) { 
	    try {
	      DynamicClassLoader dcl = new DynamicClassLoader();
	      Class c = dcl.loadClass(className);
	      if (c != null) {
	        StringBuffer sb = new StringBuffer (3000);
	        sb.append(START_LIST); 
	        sb.append(NL);
	        listClassInfo(c, level, sb);
	        sb.append(END_PAREN);
	        sb.append(NL);
	
	        Writer out
	          = new BufferedWriter(new OutputStreamWriter(System.out)); 
	        try {
	          out.write(sb.toString());
	          out.flush();
	        } catch (IOException e) {
	        }
	      }
	
	So we have four separate round trips from the Emacs Lisp world to the Java world, which are quite expensive; plus we create four separate instances of DynamicClassLoader created. And this guy seems to be quite expensive as well, since according to the documentation: 
	
	* The class <code>DynamicClassLoader</code> extends the
	* abstract class <code>ClassLoader</code>.
	* This class loads the class binaries from the file system
	* all the time, it does not catch the class information. 
	
	Theoretically then we read the each jar and class file in the classpath four times for each call to jde-complete on a new class... I have not yet run all this process through a profiler (planning to) but it seems to me that making just one call that gets the complete class info and returning four lists (one for each access level) would be far less expensive, since it would allow the DynamicClassLoader to be reused and reduce the number of Emacs-Java calls. 
	
	Is that a fair assessment? Or is there a reason for this code to be this way that I am not aware of?
	
	Also, we have a parallel method to read class information in the jde-usages package, that uses the ASM library. Which one is more efficient? Wouldn't it be benefitial to unify the two methods so that JDEE has one single source of (hopefully cached) class information for usage, completion and one day quick fixes and other simple refactorings? 
	
	Thanks,
	  Nascif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.