Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 278753 - Performance problems in MWE when used in a plugin
Summary: Performance problems in MWE when used in a plugin
Status: RESOLVED FIXED
Alias: None
Product: EMFT
Classification: Modeling
Component: MWE (show other bugs)
Version: 0.7   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: SR2   Edit
Assignee: Sebastian Zarnekow CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 278388 (view as bug list)
Depends on:
Blocks:
 
Reported: 2009-06-02 06:48 EDT by Kai Kreuzer CLA
Modified: 2011-05-20 05:10 EDT (History)
9 users (show)

See Also:


Attachments
Test project for reproducing the problem (11.68 KB, application/octet-stream)
2009-06-02 06:48 EDT, Kai Kreuzer CLA
no flags Details
Screenshot from profiler (76.84 KB, image/png)
2009-06-02 06:50 EDT, Kai Kreuzer CLA
no flags Details
Proposed patch (6.47 KB, patch)
2009-06-15 10:37 EDT, Patrick Schonbach CLA
sven.efftinge: iplog+
Details | Diff
caching resource loader patch (941 bytes, patch)
2009-07-09 09:28 EDT, Knut Wannheden CLA
sven.efftinge: iplog+
Details | Diff
Proposed patch for the NPE in getResourceAsStream() (1.08 KB, patch)
2009-07-15 03:38 EDT, Kai Kreuzer CLA
sven.efftinge: iplog+
Details | Diff
Workaround for the buddy policy issue (3.36 KB, patch)
2009-07-21 12:05 EDT, Sebastian Zarnekow CLA
no flags Details | Diff
Workaround for the buddy policy issue - Update (8.12 KB, patch)
2009-07-23 06:16 EDT, Sebastian Zarnekow CLA
sven.efftinge: iplog+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kai Kreuzer CLA 2009-06-02 06:48:23 EDT
Created attachment 137980 [details]
Test project for reproducing the problem

Build ID: I20090515-1143 (RC1)
MWE/XPand version: 0.7.0v20090526 (RC1)

Steps To Reproduce:
1. Run "RunAsJava.launch" of attached test project
2. Run "RunAsPlugin.launch" of attached test project


More information:
If Xpand templates call ext helper files, which in turn refer to existing static Java methods, the MWE spends most of the overall execution time for class loading, if it is executed inside a plugin. It is much faster when being executed as a normal Java application.

To easily reproduce this behaviour, I have set up a test project, which is attached. For comparison, it contains the two launcher configurations "RunAsJava.launch" and "RunAsPlugin.launch". Both execute exactly the same code: Two MWE workflows, which loop over Integers and either do a direct output (perftest1.mwe) or use a Java helper (perftest2.mwe).

Execution times are:
 1,0 secs for RunAsJava/perftest1.mwe
 4,4 secs for RunAsJava/perftest2.mwe
 1,1 secs for RunAsPlugin/perftest1.mwe
16,4 secs for RunAsPlugin/perftest2.mwe

This shows that delegating to a Java helper always has a serious performance impact (from 1 up to 4 secs), but when being used inside a plugin this tremendously worsens to a factor of 16.
Doing profiling, it can be seen that most of the time is spent on class loading (org.eclipse.emf.mwe.core.resources.ResourceLoaderDefaultImpl.loadClass) - see attached screenshot of JProfiler.

I think the problem does not only exist for Java helper classes, but also for meta-model classes that seem to be loaded (again and again) via the same mechanism.

Maybe it's worth considering to cache these classes during a workflow execution?
Comment 1 Kai Kreuzer CLA 2009-06-02 06:50:49 EDT
Created attachment 137981 [details]
Screenshot from profiler
Comment 2 Patrick Schonbach CLA 2009-06-15 10:37:07 EDT
Created attachment 139174 [details]
Proposed patch

The attached proposed patch indeed results in a really *dramatic* performance gain. However, before applying it, it should be reviewed carefully to avoid any unwanted side effects.
Comment 3 Sven Efftinge CLA 2009-06-15 14:19:20 EDT
Caching the classes seems to be the solution.
Maybe we should just warn people that dynamic OSGi won't work then (I guess most people can live with that)
I'll review your patch. Thanks!
Comment 4 Sven Efftinge CLA 2009-06-15 14:20:01 EDT
*** Bug 278388 has been marked as a duplicate of this bug. ***
Comment 5 Knut Wannheden CLA 2009-07-06 06:09:59 EDT
What really seems to slow down the class loading is the fact that the Xtend and MWE plug-ins declare a "dependent" buddy policy. This causes the class loader to search for classes in bundles that directly or indirectly depend on the Xtend and MWE plug-ins. This takes a lot of time. What makes things even worse is that the JavaBeans meta model will also look for matching BeanInfo classes.

How about using the "registered" buddy policy instead?
Comment 6 Sven Efftinge CLA 2009-07-08 03:22:43 EDT
Thanks Knut, for finding out. It would indeed be better to have a
registered buddy-policy instead. But changing it now would break clients.
Therefore I'ld prefer to go with the caching for now.
Comment 7 Sven Efftinge CLA 2009-07-08 03:53:42 EDT
I've added a CachingResourceLoader which can be (need to be) configured like this:

ResourceLoaderFactory.setCurrentThreadResourceLoader(
  new CachingResourceLoader(
    new ResourceLoaderImpl(classLoader)
  )
);

Does it help? Is it sufficient?

So by default the caching is *not active*! As soon as you need performance improvements due to use of JavaBeansMetamodel in an OSGi environment you should add the three lines above.
Comment 8 Knut Wannheden CLA 2009-07-09 09:28:07 EDT
Created attachment 141199 [details]
caching resource loader patch

Hi Sven,

Thanks. The CachingResourceLoaderImpl doesn't implement the ResourceLoader interface. Please see attached patch.
Comment 9 Sven Efftinge CLA 2009-07-09 09:52:58 EDT
Ups, sorry :-|
Comment 10 Kai Kreuzer CLA 2009-07-15 03:37:06 EDT
Hi Sven,

Thanks a lot for this fix, it indeed improves the performance dramatically.

Just a few final remarks/questions from my side:

1. The correct code (note the previously missing "Impl" for the activation is 
ResourceLoaderFactory.setCurrentThreadResourceLoader(
  new CachingResourceLoaderImpl(
    new ResourceLoaderImpl(classLoader)
  )
);
Will this be documented clearly anywhere in the official docs? Or how can it be made sure that nobody files similar bug reports about the same in future?

2. The CachingResourceLoaderImpl throws a NPE in getResourceAsStream() if a resource cannot be found; this is different from the default implementation and should be changed. I have attached a patch (which I have successfully tested) and reopened this issue.

Thanks again for your help,
Kai
Comment 11 Kai Kreuzer CLA 2009-07-15 03:38:19 EDT
Created attachment 141606 [details]
Proposed patch for the NPE in getResourceAsStream()
Comment 12 Patrick Schonbach CLA 2009-07-15 04:22:10 EDT
Shall we include Kai's patch for SR1?
Comment 13 Sebastian Zarnekow CLA 2009-07-15 04:27:05 EDT
Looks good so far, please apply the patch.
Comment 14 Patrick Schonbach CLA 2009-07-15 05:48:38 EDT
Patch applied to HEAD
Comment 15 Sven Efftinge CLA 2009-07-17 08:02:41 EDT
It seems that even with the caching ResourceLoader the JavaBeansMetamodel is still significantly slower in an OSGi environment than in a standard Java process.
We'll have to investigate (profile) what the reason is.
Targeting for the next bugfix release (0.7.2), which is planned for August 7th.
Comment 16 Patrick Schonbach CLA 2009-07-17 08:14:06 EDT
Ok. Do you happen to have a rest project for profiling?
Comment 17 Sebastian Zarnekow CLA 2009-07-17 08:43:57 EDT
I'll have a look at it.
Comment 18 Sebastian Zarnekow CLA 2009-07-21 12:05:10 EDT
Created attachment 142151 [details]
Workaround for the buddy policy issue

The patch contains another implementation of the ResourceLoader interface, that requires an explicit bundle id as class loading context. This is times faster than the buddy classloading that is done by the default implementation. 

The resource loader factory should be configured like this in case of serious performance issues with OSGI classloading:

CachingResourceLoaderImpl crl = new CachingResourceLoaderImpl(new OsgiResourceLoader(
	Activator.PLUGIN_ID, // a plugin that has declared the required deps explicitly
	MWEPlugin.INSTANCE.getBaseURL(), 
	RunWorkflows.class.getClassLoader())); // a class from this plugin
ResourceLoaderFactory.setCurrentThreadResourceLoader(crl);

Please verify this patch.
Comment 19 Knut Wannheden CLA 2009-07-23 04:06:04 EDT
The new OsgiResourceLoader appears to nicely circumvent the performance problems caused by the buddy policy!

I get the impression that the MWE plug-in's base URL is only required by the WorkflowRunner internally; e.g. to load and display the MWE version (see WorkflowRunner#getVersion()). If that is true then it would maybe be possible to load the version without using the ResourceLoader (possibly using WorkflowRunner.class.getClassLoader()) or just hide that detail by not requiring the baseURL constructor parameter. This is also "problematic" as the class MWEPlugin is in an "internal" package. An alternative for the developer is of course: Platform.getBundle("org.eclipse.emf.mwe.core").getEntry("/").

I like the fact that methods like getResource(String) are not declared as final.

(In reply to comment #18)
> Created an attachment (id=142151) [details]
> Workaround for the buddy policy issue
> 
> The patch contains another implementation of the ResourceLoader interface, that
> requires an explicit bundle id as class loading context. This is times faster
> than the buddy classloading that is done by the default implementation. 
> 
> The resource loader factory should be configured like this in case of serious
> performance issues with OSGI classloading:
> 
> CachingResourceLoaderImpl crl = new CachingResourceLoaderImpl(new
> OsgiResourceLoader(
>         Activator.PLUGIN_ID, // a plugin that has declared the required deps
> explicitly
>         MWEPlugin.INSTANCE.getBaseURL(), 
>         RunWorkflows.class.getClassLoader())); // a class from this plugin
> ResourceLoaderFactory.setCurrentThreadResourceLoader(crl);
> 
> Please verify this patch.
> 

Comment 20 Sebastian Zarnekow CLA 2009-07-23 06:16:21 EDT
Created attachment 142361 [details]
Workaround for the buddy policy issue - Update

This patch supersedes the previous attachement and incorporates Knut's suggestion.
Comment 21 Sebastian Zarnekow CLA 2009-07-27 08:05:21 EDT
Committed to HEAD.