This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 49115 - [perf] MDR generates the same classes each IDE invocation
Summary: [perf] MDR generates the same classes each IDE invocation
Status: CLOSED FIXED
Alias: None
Product: java
Classification: Unclassified
Component: Unsupported (show other bugs)
Version: 4.x
Hardware: All All
: P3 blocker (vote)
Assignee: Daniel Prusa
URL:
Keywords: PERFORMANCE
Depends on:
Blocks: 49990
  Show dependency tree
 
Reported: 2004-09-15 19:31 UTC by _ tball
Modified: 2006-03-24 09:59 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description _ tball 2004-09-15 19:31:21 UTC
MDR has its own proxy class generation facility,
which generates over a hundred JMI implementation
classes each time NetBeans runs.  To check this, I
added a println statement to the top of
org.netbeans.mdr.handlers.gen.HandlerGenerator.generateHandler().
 

Try adding a print line there and watch as classes
mainly get generated during three
performance-critical activities:

1.  after the main window displays for the first
time but before your CPU meter drops to zero;

2.  during classpath scanning; and

3.  the first time you open a class to view its
members in the Explorer.
 
Shouldn't these generated classes be created
during the build like the rest of our classes? 
The Java language won't be changing any time soon
(and certainly not between every IDE invocation!).
 Better yet, since javacore implements the same
JMI interfaces that the generated handlers do, how
about merging the functionality of these classes?
 It seems that a single, static implementation
would perform much better and take less footprint.

Also, a separate set of interface implementations
are generated by MDR to initialize its repository
files for the first time.  MDR initialization
could instead be run during installation, since
MDR can be (or used to be) executable from the
command line.
Comment 1 Martin Matula 2004-09-23 12:48:02 UTC
The interface implementations are generated dynamically not because we
thought that java language will change often, but because:
1) we want to avoid regenerating all metamodel implementations if the
MDR byte code generator is updated (we fix some bug, etc.) - this way
the new version of MDR can be distributed using autoupdate without a
need for regenerating all metamodel implementations installed on
user's machine
2) the assumption was the byte code generation is not significanlty
slower than loading classes from the disk (I see no indication in this
issue that this is not the case)

There is a separate issue filed regarding the MDR initialization
during installation (see issue 45054).
Comment 2 _ rkubacki 2004-09-24 13:26:35 UTC
re 1): you need to update users instalation anyway, either with
bytecode generator or with new version of generated classes. there is
no advantage in current approach IMO.

re 2): have you measured this before you made this assumption? How
many classes do we need to generate? How many classes of bytecode
generator do we need to load to make this system working. IMO you can
spent hundreds of milliseconds in generator (can be checked with some
profiler). Of course more garbage is produced during this time than
with usual classloading. Average time to load a class is less than 1
ms. Cf. 'jstat -class' or other tools to see how much time JVM spents
in classloading. 
Comment 3 Martin Matula 2004-09-24 13:42:40 UTC
re re 1) the advantage seems obvious to me - while in the case of
dynamic bytecode generation the MDR module maintainer can just change
the MDR module and all the other applications/modules build on top of
it will automatically adapt the change - no additional work needed, in
the static bytecode generation with every change to the MDR and the
bytecode generator (bugfixing, etc.) we would have to notify everyone
to regenerate their implementations.

re re 2) I haven't measured it yet, but bytecode generation never
caused a noticable delay and I never saw it as a significant
performance blocker when profiling MDR and javacore. 

Anyway, note I haven't closed this issue as INVALID or WONTFIX. I am
going to change MDR to store generated classes in the b-tree so that
they do not need to be generated over and over again. The classes will
be properly versioned so that if someone changes the generator or the
metamodel, they will get regenerated again. Happy?
Comment 4 _ rkubacki 2004-09-24 21:11:01 UTC
I am not quite convinced that this is the best approach but it is
going to be an improvements ;-) So the assumption is that reading from
btreestorage is comparable to our ProxyClassLoader. It might be.
Wouldn't it be easier for testability too to dump them into normal
files (and avoid special classloader)? OK, I do not have strong
opinion here.

If I recall correctly there were also some string containing method
signatures for generated classes. I expect that data like these are
not needed if we implement this so it can be another benefit.
Comment 5 Petr Nejedly 2004-10-06 13:09:17 UTC
Hmm, I have measured that the IDE spends ~1.5s in generateHandler
during the startup with some project open.

Note that mentioned 1.5s is on 2GHz NTB when I tried to reduce paralel
threads running on the machine (If I just measured dusing
currentTimeMillis on unmodified startup, I got nearly 3s)

First few classes take most of the time as the generator is running
interpretted and may be even JITted during execution.

Removing the runtime generation step, we'll also save some time spent
loading the generator classes and the memory used by the generator
classes (~100kB jist in .class files which may consume much more once
loaded).
Comment 6 _ rkubacki 2004-10-07 14:31:14 UTC
Trying with build from Oct 4, JDK 1.5.0 on Solaris ULTRA 60 with
sampling by Analyzer every 1ms. My startup with 2 project and soem
Java editors takes ~95s and 3.260ms is spent in
HandlerGenerator.generateHandler. These are 3% of total startup time. 

As Petr mentioned all the stuff related to runtime generation is
almost 100kB of classes, it holds some data for generation and likely
only small part of this system will be optimized by hotspot. It
generates ~400kB for 88 classes in my case (probably couple more
classes can be generated later).

BTree database vs. ProxyClassLoader - once you dump the classes it is
quite easy to package them and refer to them in your modules. If you
want to store them in database you need to have special classloader
and there will be some overhead related to maintainance of btree
structures and versioning.
Comment 7 Martin Matula 2004-10-13 11:22:58 UTC
Dan is going to fix this.
Comment 8 Daniel Prusa 2004-10-15 12:46:13 UTC
Checking in handlers/gen/HandlerGenerator.java;
/cvs/mdr/src/org/netbeans/mdr/handlers/gen/HandlerGenerator.java,v 
<--  HandlerGenerator.java
new revision: 1.14; previous revision: 1.13
done
Processing log script arguments...
More commits to come...
Checking in storagemodel/StorableObject.java;
/cvs/mdr/src/org/netbeans/mdr/storagemodel/StorableObject.java,v  <--
 StorableObject.java
new revision: 1.41; previous revision: 1.40
done
Processing log script arguments...
More commits to come...
Checking in util/IOUtils.java;
/cvs/mdr/src/org/netbeans/mdr/util/IOUtils.java,v  <--  IOUtils.java
new revision: 1.32; previous revision: 1.31
done
Comment 9 Petr Nejedly 2004-10-15 17:45:12 UTC
Would it be possible to move the caching logic out of the
HandlerGenerator to its caller (BaseObjectHandler I guess)?
Doing this change, you can spare loading the generator classes, which
are huge.
(with verification on, most of the gen package is still loaded, but
even with verification off, we can spare 4 classes, 2 of them quite big).
Comment 10 Martin Matula 2004-10-15 18:25:44 UTC
Good idea!
Comment 11 Daniel Prusa 2004-10-18 13:57:02 UTC
Done.

/cvs/mdr/src/org/netbeans/mdr/handlers/BaseObjectHandler.java
new revision: 1.47; previous revision: 1.46

/cvs/mdr/src/org/netbeans/mdr/handlers/gen/HandlerGenerator.java
new revision: 1.15; previous revision: 1.14
Comment 12 _ rkubacki 2004-10-21 13:34:43 UTC
HandlerGenerator is not loaded in build from Oct 20,
BaseObjectHandler.resolveClass takes 379ms