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