- Java EE 8 High Performance
- Romain Manni Bucau
- 459字
- 2021-06-30 19:14:27
Events
CDI events globally provide an event BUS inside the application. They can be synchronous or asynchronous. To let you have an idea, here is what the code can look like:
@ApplicationScoped
public class LifecycleManager {
@Inject
private Event<Starting> startingEvent;
public void starting() {
final Starting event = new Starting();
startingEvent.fire(event);
startingEvent.fireAsync(event);
}
}
As both types of invocations are exclusive, what we can note here is that these snippets call fire() and fireAsync(). To be able to target all the observers, you need to invoke both. This means that the associated logic will be twice.
Without entering into the details that do not impact our performance, both cases share the same resolution mechanism:
- Resolve the observers based on the event type.
- Remove the observers not matching the fire type (asynchronous or synchronous).
- Sort the observers by priority.
- Handle the invocations.
The difference between synchronous and asynchronous cases is point 4. In the synchronous case, it just means, invoke the observers, whereas in the asynchronous case, it means, call asynchronously and return CompletionStage representing all the invocation results.
The parts impacting the performance are the resolution of the observers and the invocation, which can require some bean resolution.
We already saw bean resolution, so let's dig into the observer resolution here. Indeed, the implementation is specific to the vendor you are using. But, as it is impossible to use static analysis to implement this part, the resolution is done at runtime with a cache per event type. Note that the caching depends a lot on the implementation. Most will only cache raw type events.
This concretely means that the invocation without generics, as shown in the following code, will be way faster than the invocation that implements generics and enforces the CDI container to do some more resolution:
event.fire(new MyEvent());
In terms of the code, and to let you compare it with the previous example, the code with generics would be exactly the same except the event would be parameterized:
event.fire(new MyEvent<String>());
Then, once you have the potential set of observers, you need to reduce the set based on the qualifiers that the caller configures for the event. This also implies some reflection, more or less cached, depending on the implementation.
Finally, some runtime checks are enforced by the set of tests that the vendors have to pass so that we can claim to be compliant with the specifications.
All these steps are more or less optimized by vendors depending on the cases they may have received complaints about. But in all of them, you can end up on code paths where everything is done at runtime for the firing of each event, which can be a pain in terms of the performance.
- Linux實戰
- Arch Linux Environment Setup How-to
- WindowsServer2012Hyper-V虛擬化部署與管理指南
- 混沌工程實戰:手把手教你實現系統穩定性
- Windows Server 2012網絡操作系統企業應用案例詳解
- 從實踐中學習Kali Linux無線網絡滲透測試
- Python UNIX和Linux系統管理指南
- VMware Horizon View Essentials
- Kali Linux高級滲透測試(原書第3版)
- Advanced Infrastructure Penetration Testing
- 統信UOS應用開發進階教程
- Agile IT Security Implementation Methodology
- Learn Quantum Computing with Python and IBM Quantum Experience
- Linux系統安全:縱深防御、安全掃描與入侵檢測
- 辦公自動化教程(Windows7+Office2010)