XText 2.4.3 to 2.8.2 performance problems in getDeclaredMethods and isReadOnly [message #1695497] |
Fri, 15 May 2015 10:16 |
Sergio Otero Messages: 39 Registered: June 2012 |
Member |
|
|
Hi
We're migrating a project with a very large grammar (2000 lines) that is used in projects with 8.000 files that occupy a total of 150Mb.
It seems to be taking longer than before. With JVisualVM i've seen that
org.eclipse.xtext.builder.clustering.ClusteringBuilderState.doUpdate() 100.0 105.562 ms (100%) 105.562 ms
org.eclipse.xtext.EcoreUtil2.resolveLazyCrossReferences() 37.76996 39.870 ms (37,8%) 39.870 ms
org.eclipse.xtext.builder.clustering.ClusteringBuilderState.installSourceLevelURIs() 27.822605 29.370 ms (27,8%) 29.370 ms
org.eclipse.xtext.ui.resource.DefaultResourceUIServiceProvider.isReadOnly() 27.81468 29.361 ms (27,8%) 29.361 ms
org.eclipse.xtext.builder.builderState.AbstractBuilderState.updateMarkers() 14.870227 15.697 ms (14,9%) 15.697 ms
org.eclipse.xtext.builder.resourceloader.AbstractResourceLoader$CheckedLoadOperation.next() 10.326545 10.900 ms (10,3%) 10.900 ms
org.eclipse.xtext.builder.builderState.BuilderStateUtil.create() 5.5819836 5.892 ms (5,6%) 5.892 ms
The method installSourceLevelURIs is new to Xtext 2.8 and it is called every time clusteringPolicy.continueProcessing returns false (because our custom clusteringpolicy determines that there's not enought memory to continue without cleaning).
It seems to try to determine if every resource is readonly and it takes 30% of the linking phase.
Why is this needed?
Could i extend IResourceServiceProviderExtension to return "isReadOnly" to false always?
Maybe better extend ClusteringBuilderState to avoid calling to isReadOnly?
The first method resolveLazyCrossReferences consume 37% of time. Almost 1/3 of this time is due to class.getDeclaredMethod. This is because Java makes a copy of the declared methods to avoid anyone changing the info.
I've solved this problem in many applicacions with a guava cache with soft references.
org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.polymorphicFindScopeForReferenceName() 16.161259 17.060 ms (16,2%) 17.060 ms 86
org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider$2.<init>() 12.731248 13.439 ms (12,7%) 13.439 ms 61
org.eclipse.xtext.util.PolymorphicDispatcher.<init>() 12.731248 13.439 ms (12,7%) 13.439 ms 61
org.eclipse.xtext.util.PolymorphicDispatcher.getDeclaredMethodsOrderedBySpecificParameterType() 12.713763 13.420 ms (12,7%) 13.420 ms 61
java.lang.Class.getDeclaredMethods() 12.713763 13.420 ms (12,7%) 13.420 ms 61
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
Thanks
Sergio
|
|
|
|
Re: XText 2.4.3 to 2.8.2 performance problems in getDeclaredMethods and isReadOnly [message #1695508 is a reply to message #1695504] |
Fri, 15 May 2015 12:52 |
Sergio Otero Messages: 39 Registered: June 2012 |
Member |
|
|
Ok, i will open 2 tickets
I have easyly overriden DefaultResourceUIServiceProvider to return isReadOnly always to false, but the other problem is not so easy to do.
For what i can see, PolymorphicDispatcher cannot be cached, so i have to extend it and overwrite getDeclaredMethodsOrderedBySpecificParameterType.
Then and i have to overwrite also AbstractDeclarativeScopeProvider.polymorphicFindScopeForReferenceName and polymorphicFindScopeForClassName, duplicating it's code, which is ugly ...
protected IScope polymorphicFindScopeForReferenceName(EObject context, EReference reference) {
Predicate<Method> predicate = getPredicate(context, reference);
PolymorphicDispatcher<IScope> dispatcher = new PolymorphicDispatcherParcheRend<IScope>(Collections
.singletonList(this), predicate, errorHandler) {
@Override
protected IScope handleNoSuchMethod(Object... params) {
if (PolymorphicDispatcher.NullErrorHandler.class.equals(errorHandler.getClass()))
return null;
return super.handleNoSuchMethod(params);
}
};
EObject current = context;
IScope scope = null;
while (scope == null && current != null) {
scope = dispatcher.invoke(current, reference);
current = current.eContainer();
}
return scope;
}
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03630 seconds