eclipse / elk

Eclipse Layout Kernel - Automatic layout for Java applications.
https://www.eclipse.org/elk/
Other
239 stars 82 forks source link

Over-enthusiastic org.eclipse.elk.graph.text.convert loading #1026

Open ewillink opened 2 months ago

ewillink commented 2 months ago

ELK contributes menu actions that are activated by the Sample Ecore Model Editor. An attempt to show the menu results in excessive activity as shown by the stack trace below for the org.eclipse.elk.graph.text.convert commandId.

Eclipse UI functionality needs to be lazy to avoid imposing activation costs of all possible UI contributors on all possible consumers.

When contributing to generic menus, the contribution should be as lightweight as possible. In particular no Xtext parsing should occur until the user actually selects the org.eclipse.elk.graph.text.convert command for execution.

Thread [main] (Suspended (breakpoint at line 121 in ResourceSetImpl)) owns: GrammarProvider (id=627) owns: Collections$SynchronizedMap<K,V> (id=628) SynchronizedXtextResourceSet(ResourceSetImpl).<init>() line: 121 SynchronizedXtextResourceSet(XtextResourceSet).<init>() line: 191 SynchronizedXtextResourceSet.<init>() line: 27 SynchronizedXtextResourceSet$$FastClassByGuice$$274b361.GUICE$TRAMPOLINE(int, Object, Object[]) line: not available SynchronizedXtextResourceSet$$FastClassByGuice$$274b361.apply(Object, Object) line: not available DefaultConstructionProxyFactory$FastClassProxy<T>.newInstance(Object...) line: 82 ConstructorInjector<T>.provision(InternalContext, ConstructionContext<T>) line: 114 ConstructorInjector<T>.construct(InternalContext, Dependency<?>, ProvisionListenerStackCallback<T>) line: 91 ConstructorBindingImpl$Factory<T>.get(InternalContext, Dependency<?>, boolean) line: 300 FactoryProxy<T>.get(InternalContext, Dependency<?>, boolean) line: 60 InjectorImpl$1.get() line: 1148 GrammarProvider.doGetGrammar(Object) line: 62 GrammarProvider.getGrammar(Object) line: 53 TerminalsGrammarAccess.internalFindGrammar(GrammarProvider) line: 48 TerminalsGrammarAccess.<init>(GrammarProvider) line: 37 TerminalsGrammarAccess$$FastClassByGuice$$f9a4b47.GUICE$TRAMPOLINE(int, Object, Object[]) line: not available TerminalsGrammarAccess$$FastClassByGuice$$f9a4b47.apply(Object, Object) line: not available DefaultConstructionProxyFactory$FastClassProxy<T>.newInstance(Object...) line: 82 ConstructorInjector<T>.provision(InternalContext, ConstructionContext<T>) line: 114 ConstructorInjector<T>.construct(InternalContext, Dependency<?>, ProvisionListenerStackCallback<T>) line: 91 ConstructorBindingImpl$Factory<T>.get(InternalContext, Dependency<?>, boolean) line: 300 ProviderToInternalFactoryAdapter<T>.get() line: 40 SingletonScope$1.get() line: 169 InternalFactoryToProviderAdapter<T>.get(InternalContext, Dependency<?>, boolean) line: 45 SingleParameterInjector<T>.inject(InternalContext) line: 40 SingleParameterInjector<T>.getAll(InternalContext, SingleParameterInjector<?>[]) line: 60 ConstructorInjector<T>.provision(InternalContext, ConstructionContext<T>) line: 113 ConstructorInjector<T>.construct(InternalContext, Dependency<?>, ProvisionListenerStackCallback<T>) line: 91 ConstructorBindingImpl$Factory<T>.get(InternalContext, Dependency<?>, boolean) line: 300 ProviderToInternalFactoryAdapter<T>.get() line: 40 SingletonScope$1.get() line: 169 InternalFactoryToProviderAdapter<T>.get(InternalContext, Dependency<?>, boolean) line: 45 FactoryProxy<T>.get(InternalContext, Dependency<?>, boolean) line: 60 SingleParameterInjector<T>.inject(InternalContext) line: 40 SingleParameterInjector<T>.getAll(InternalContext, SingleParameterInjector<?>[]) line: 60 ConstructorInjector<T>.provision(InternalContext, ConstructionContext<T>) line: 113 ConstructorInjector<T>.construct(InternalContext, Dependency<?>, ProvisionListenerStackCallback<T>) line: 91 ConstructorBindingImpl$Factory<T>.get(InternalContext, Dependency<?>, boolean) line: 300 ProviderToInternalFactoryAdapter<T>.get() line: 40 SingletonScope$1.get() line: 169 InternalFactoryToProviderAdapter<T>.get(InternalContext, Dependency<?>, boolean) line: 45 FactoryProxy<T>.get(InternalContext, Dependency<?>, boolean) line: 60 SingleFieldInjector.inject(InternalContext, Object) line: 50 MembersInjectorImpl<T>.injectMembers(T, InternalContext, boolean) line: 146 ConstructorInjector<T>.provision(InternalContext, ConstructionContext<T>) line: 124 ConstructorInjector<T>.construct(InternalContext, Dependency<?>, ProvisionListenerStackCallback<T>) line: 91 ConstructorBindingImpl$Factory<T>.get(InternalContext, Dependency<?>, boolean) line: 300 ProviderToInternalFactoryAdapter<T>.get() line: 40 SingletonScope$1.get() line: 169 InternalFactoryToProviderAdapter<T>.get(InternalContext, Dependency<?>, boolean) line: 45 InternalInjectorCreator.loadEagerSingletons(InjectorImpl, Stage, Errors) line: 213 InternalInjectorCreator.injectDynamically() line: 186 InternalInjectorCreator.build() line: 113 Guice.createInjector(Stage, Iterable<Module>) line: 87 Guice.createInjector(Iterable<Module>) line: 69 Guice.createInjector(Module...) line: 59 ElkGraphTextUiActivator.createInjector(String) line: 39 ElkGraphTextUiActivator(TextActivator).getInjector(String) line: 61 ElkGraphExecutableExtensionFactory.getInjector() line: 30 ElkGraphExecutableExtensionFactory(AbstractGuiceAwareExecutableExtensionFactory).create() line: 54 ConfigurationElement.createExecutableExtension(String) line: 276 ConfigurationElementHandle.createExecutableExtension(String) line: 65 HandlerProxy.loadHandler() line: 336 HandlerProxy.setEnabled(Object) line: 221 E4HandlerProxy.setEnabled(IEclipseContext, IEvaluationContext) line: 134 GeneratedMethodAccessor9.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 568 MethodRequestor.execute() line: 58 InjectorImpl.invokeUsingClass(Object, Class<?>, Class<Annotation>, Object, PrimaryObjectSupplier, PrimaryObjectSupplier, boolean, boolean, boolean) line: 298 InjectorImpl.invoke(Object, Class<Annotation>, Object, PrimaryObjectSupplier, PrimaryObjectSupplier) line: 232 ContextInjectionFactory.invoke(Object, Class<Annotation>, IEclipseContext, IEclipseContext, Object) line: 174 WorkbenchHandlerServiceHandler(HandlerServiceHandler).setEnabled(Object) line: 91 Command.setEnabled(Object) line: 856 HandlerServiceImpl.canExecute(ParameterizedCommand, IEclipseContext) line: 170 MenuManagerRendererFilter.updateElementVisibility(MMenu, MenuManagerRenderer, MenuManager, IEclipseContext, int, boolean) line: 202 MenuManagerShowProcessor.showMenu(MMenu, MenuManager) line: 248 MenuManagerShowProcessor.menuAboutToHide(IMenuManager) line: 114 MenuManagerEventHelper.showEventPostHelper(MenuManager) line: 89 MenuManager.handleAboutToShow() line: 468 MenuManager$2.menuShown(MenuEvent) line: 494 TypedListener.handleEvent(Event) line: 259 EventTable.sendEvent(Event) line: 89 Display.sendEvent(EventTable, Event) line: 4274 Menu(Widget).sendEvent(Event) line: 1066 Menu(Widget).sendEvent(int, Event, boolean) line: 1090 Menu(Widget).sendEvent(int) line: 1071 Shell(Control).WM_INITMENUPOPUP(long, long) line: 5141 Shell(Control).windowProc(long, int, long, long) line: 4773 Shell(Canvas).windowProc(long, int, long, long) line: 340 Shell(Decorations).windowProc(long, int, long, long) line: 1478 Shell.windowProc(long, int, long, long) line: 2305 Display.windowProc(long, long, long, long) line: 5039 OS.TrackPopupMenu(long, int, int, int, int, long, RECT) line: not available [native method] Menu._setVisible(boolean) line: 237 Display.runPopups() line: 4113 Display.readAndDispatch() line: 3654 PartRenderingEngine$5.run() line: 1151 Realm.runWithDefault(Realm, Runnable) line: 339 PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 1042 E4Workbench.createAndRunUI(MApplicationElement) line: 152 Workbench.lambda$3(Display, WorkbenchAdvisor, int[]) line: 639 0x000002059a1d6478.run() line: not available Realm.runWithDefault(Realm, Runnable) line: 339 Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 546 PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 173 IDEApplication.start(IApplicationContext) line: 152 EclipseAppHandle.run(Object) line: 208 EclipseAppLauncher.runApplication(Object) line: 143 EclipseAppLauncher.start(Object) line: 109 EclipseStarter.run(Object) line: 439 EclipseStarter.run(String[], Runnable) line: 271 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 77 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 568 Main.invokeFramework(String[], URL[]) line: 651 Main.basicRun(String[]) line: 588 Main.run(String[]) line: 1459 Main.main(String[]) line: 1432

soerendomroes commented 2 months ago

Thanks for notifying us about this. We try to tackle this for the next release and if you know how to solve this PRs are very much appreciated.

ewillink commented 2 months ago

Usually the problem with menu actions is to avoid locking out the UI by moving the too-costly action code to a worker thread.

However this seems to be an initialization problem, so whatever provokes the parsing when declaring the menu entry should be moved to a lazy initialization from the action code so that it is not incurred till needed, possibly in a worker thread.

However again, there may be a greater inefficiency. When I scan the menu entries visually in the UI, I see nothing that looks like a text convert. Perhaps the menu contribution is being incorrectly declared or being declared for an inappropriate context.