Event Driven
9
min of reading
November 10, 2020

Optimizing Event Driven Architecture in Java (from the low level)

Charles Fonseca
I develop systems to make humanity's life easier.
More about the author
Back

Event Driven Architecture is widespread in the market, however, when using it without care, there may be unsatisfactory levels in relation to those promised by evangelists. This post addresses the theme in a very objective and detailed way.When we use this architectural model, we are looking for high performance, as it handles, in general, real-time streaming, batch, jobs, etc. There are several possible optimizations to be made in this model when it comes to Java, which has proven to be a tool option for this purpose.The implementation of the Java Virtual Machine (JVM), Eclipse OpenJ9, has been innovating in several aspects, providing a paradigm for Java applications. They decoupled the Just-In-Time (JIT) compilation from the rest of the compiler, establishing the concept of JIT server.The idea is for the application to run independently of its runtime optimizer (JIT). What problem does this solve? Suppose the following architecture, all Message Consumers are instances of the same application, and the queue is a messaging service, like RabbitMQ, Apache ActiveMQ.Each consumer in the queue is a Java application, with its own compiler, each one, therefore, will have CPU cycles dedicated to JIT, and dedicated memory. All instances will perform the same optimization process at run time, since they have the same processes, which can cause performance losses in the application.With the JIT server, it is possible to have an isolated server dedicated to meeting compilation requests for all applications. It has more bytecode optimization information than a common compiler would have, since there are more instances, consequently, more hotspots.

There is no free lunch

All the improvements mentioned, however, are not possible without cost. The application and the compiler communicate via network protocols. However, builds take longer due to network latency, but on the other hand, the JVM is no longer depleting CPU or memory cycles on the JIT build.The bottleneck is proportional to the number of instances running. So, the fewer instances, the less information the JIT will have to optimize the resources. In addition, decreasing network latency can certainly be beneficial for the application.Benchmarks established by OpenJ9 can be checked here.

Hands-on

You can install OpenJ9 through SDKMAN:

curl -s "https://get.sdkman.io" | bashsdk i java x.x.x.j9-adptOr using the official website, selecting the option OpenJ9.

Then, execute:

jitserver -Xjit:verbose

With that, it will upload a server on its default port, and we will obtain greater visibility of the compilation processes by adding the parameter.To use the jitserver add the `-XX: + UseJITServer` flag when running the application, with that, it will be able to connect automatically. If the jitserver is unavailable, or the application cannot connect, it will use its own compilation processes, with no loss of performance at the low level.

Node.java

In addition to low-level optimizations, following Event Driven Architecture, the Eclipse Vert.x framework is a great choice considering its internal operation. Under the hood, the framework works through the Event Bus, which works as the Event Emitter of Node.js. The application has a process queue, so that both the framework and the application can emit and listen to events. Thus, it is possible to cluster the event queue of several Vert.x applications, obtaining high performance without the need to block the main thread, or deplete HTTP/HTTPS resources, which have additional layers of communication, and occur through bridges. Not only is this communication possible between Java applications, but also with Node applications through the aforementioned Event Emitter, and even with the browser through SocketJS.

Related readings

Thanks for reading!