Hi !

I'm facing a very innefficient piece of code while trying to play around
teh OpenLDAP ACl editor. Here is what I do, and what I see.

- I connect to an OpenLDAP remote server
- I pick a MDB database entry (but that could be any entry which contain
the olcAccess attributeType (every ObjectClass inheriting from
olcDatabaseConfig, ie, any backend).
- I open it, and get all the attributes and values in it
- assuming there is at least one olcAccess instance in this entry, then
the OpenLdapAclValueWithContext constructor is called 28 times !

The reason is that we are iterating across all the TreeViexer
selectionChangeListeners, and we have many (62... One per editor).

This starts in :

    protected void fireSelectionChanged(final SelectionChangedEvent event) {
        Object[] listeners = selectionChangedListeners.getListeners();
        for (Object listener : listeners) {
            final ISelectionChangedListener l =
(ISelectionChangedListener) listener;
            SafeRunnable.run(new SafeRunnable() {
                @Override
                public void run() {
                    l.selectionChanged(event); ---> This get called as
many times as we have listeners
                }
            });
        }
    }

Each loop invokes the EntryEditorActionProxy.selectionChanged() method,
then the BrowserActionProxy.updateAction(), which calls
OpenEditorAction.isEnabled(), which calls the
EntryEditorWidgetCellModifier.canModify() method, which tries to figure
out what is the best editor for the selected value, and finally call the
getRawValue() of the class used to edit the value.

In my case, it ends up calling the ACL parser as many times we have
listeners (28 times), even if the listeners are totally unrelated.

Here is the stack trace :

Thread [main] (Suspended (breakpoint at line 143 in
OpenLdapAclValueEditor))   
    OpenLdapAclValueEditor.getRawValue(IValue) line: 143   
    EntryEditorWidgetCellModifier.canModify(Object, String) line: 79   
    OpenEditorAction.isEnabled() line: 128   
    EntryEditorActionProxy(BrowserActionProxy).updateAction() line: 248   
   
EntryEditorActionProxy(BrowserActionProxy).selectionChanged(SelectionChangedEvent)
line: 237   
    Viewer$2.run() line: 163   
    SafeRunner.run(ISafeRunnable) line: 42   
    JFaceUtil$1.run(ISafeRunnable) line: 50   
    SafeRunnable.run(ISafeRunnable) line: 178   
>>>>TreeViewer(Viewer).fireSelectionChanged(SelectionChangedEvent) line:
160<<<<---------------- Starting loop   
    TreeViewer(StructuredViewer).updateSelection(ISelection) line: 2171   
    TreeViewer(StructuredViewer).handleSelect(SelectionEvent) line: 1202   
    StructuredViewer$4.widgetSelected(SelectionEvent) line: 1231   
    OpenStrategy.fireSelectionEvent(SelectionEvent) line: 242   
    OpenStrategy.access$4(OpenStrategy, SelectionEvent) line: 236   
    OpenStrategy$1.handleEvent(Event) line: 408   
    EventTable.sendEvent(Event) line: 84   
    Display.sendEvent(EventTable, Event) line: 4199   
    Tree(Widget).sendEvent(Event) line: 1467   
    Tree(Widget).sendEvent(int, Event, boolean) line: 1490   
    Tree(Widget).sendEvent(int, Event) line: 1475   
    Tree(Widget).notifyListeners(int, Event) line: 1279   
    Display.runDeferredEvents() line: 4042   
    Display.applicationNextEventMatchingMask(long, long, long, long,
long, long) line: 4996   
    Display.applicationProc(long, long, long, long, long, long) line:
5378   
    OS.objc_msgSendSuper(objc_super, long, long) line: not available
[native method]   
    Tree(Widget).callSuper(long, long, long) line: 221   
    Tree(Widget).mouseDownSuper(long, long, long) line: 1101   
    Tree.mouseDownSuper(long, long, long) line: 2064   
    Tree(Widget).mouseDown(long, long, long) line: 1093   
    Tree(Control).mouseDown(long, long, long) line: 2563   
    Tree.mouseDown(long, long, long) line: 2032   
    Display.windowProc(long, long, long) line: 5638   
    OS.objc_msgSendSuper(objc_super, long, long) line: not available
[native method]   
    Shell(Widget).callSuper(long, long, long) line: 221   
    Shell(Widget).windowSendEvent(long, long, long) line: 2105   
    Shell.windowSendEvent(long, long, long) line: 2329   
    Display.windowProc(long, long, long) line: 5702   
    OS.objc_msgSendSuper(objc_super, long, long) line: not available
[native method]   
    Display.applicationSendEvent(long, long, long) line: 5139   
    Display.applicationProc(long, long, long) line: 5288   
    OS.objc_msgSend(long, long, long) line: not available [native
method]   
    NSApplication.sendEvent(NSEvent) line: 128   
    Display.readAndDispatch() line: 3666   
    PartRenderingEngine$9.run() line: 1151   
    Realm.runWithDefault(Realm, Runnable) line: 332   
    PartRenderingEngine.run(MApplicationElement, IEclipseContext) line:
1032   
    E4Workbench.createAndRunUI(MApplicationElement) line: 148   
    Workbench$5.run() line: 636   
    Realm.runWithDefault(Realm, Runnable) line: 332   
    Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 579   
    PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line:
150   
    Application.start(IApplicationContext) line: 51   
    EclipseAppHandle.run(Object) line: 196   
    EclipseAppLauncher.runApplication(Object) line: 134   
    EclipseAppLauncher.start(Object) line: 104   
    EclipseStarter.run(Object) line: 380   
    EclipseStarter.run(String[], Runnable) line: 235   
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not
available [native method]   
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62   
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43   
    Method.invoke(Object, Object...) line: 497   
    Main.invokeFramework(String[], URL[]) line: 648   
    Main.basicRun(String[]) line: 603   
    Main.run(String[]) line: 1465   
    Main.main(String[]) line: 1438   


The question would be : how can we avoid such thing to happen ?

Reply via email to