scijava-common icon indicating copy to clipboard operation
scijava-common copied to clipboard

DefaultEventBus#publishLater should use queue instead of run

Open hinerm opened this issue 10 years ago • 7 comments

@dscho and @ctrueden -

Is it possible that having publishLater call EventService#run instead of EventService.queue could be violating some assumptions in IJ2?

At the least we should probably document the various publish methods in DefaultEventBus, as I'm not sure the expected behavior of a publishLater method would be to run it immediately on a new thread - especially given that publishNow uses ThreadService#invoke which appears to only run threads on the EDT... so the behavior of these two methods seems reversed/counter-intuitive without documentation.

hinerm avatar Mar 21 '14 11:03 hinerm

Yes, as we discussed @hinerm, I think 6b878da41160da695f6552ee86f537cff2443faf was an error because the contract of publish, publishNow and publishLater is for them to always execute things on the EDT (for some definition of "EDT" :wink:). It may be orders of magnitude faster, but it also violates that contract, meaning that non-EDT threads now receive event notifications which has really bad ramifications.

ctrueden avatar Mar 22 '14 12:03 ctrueden

And I agree about adding javadoc for the DefaultEventBus API. (Tangentially: we should rename DefaultEventBus to SciJavaEventBus, since there is no corresponding org.scijava.event.EventBus interface.)

ctrueden avatar Mar 22 '14 12:03 ctrueden

Whatever we do, we must not have the performance regression that adds a couple of seconds to the Context creation just because events are published synchronously...

dscho avatar Mar 22 '14 16:03 dscho

@dscho: It would not be a "regression" because the "fix" that "improved performance" actually broke behavior. By the same logic, I could simply change the Context() constructor to call this(true) instead of this(false), claim an orders-of-magnitude "performance increase" and then call it a "performance regression" when someone inevitably reverts that broken change.

However, that said, of course I agree wholeheartedly that we should do whatever we can to avoid such high overhead when publishing events. But not at the cost of correctness—the event subsystem is too critical for that.

ctrueden avatar Mar 22 '14 19:03 ctrueden

A compromise, then. Start a thread that adds a thread to the EDT. So that the 100ms do not punish the current thread.

dscho avatar Mar 22 '14 21:03 dscho

@dscho: Sure, if doing that is truly faster, then I'm all for it. It's bizarre to me that calling EventQueue.invokeLater directly pays such a heavy price. :sweat:

ctrueden avatar Mar 24 '14 17:03 ctrueden

Years later, this rears its head again. When debugging some status-reporting issue with @etadobson, we noticed that dozens of new threads were spawned—in fact one per call to statusService.updateStatus(...), because it publishes a StatusEvent which in turn calls EventService#publishLater which (contrary to documentation) then calls ThreadService#run rather than ThreadService#queue. I'm going to escalate this to a bug finally, and will try to find time to implement Johannes's suggestion above to spawn a thread that queues the event to the EDT, and then test how it impacts both behavior and performance.

ctrueden avatar Feb 19 '20 20:02 ctrueden