IBM Developer

Article

Measuring energy consumption of Quarkus applications

Empower developers to make energy-aware design decisions with Quarkus

By Christophe Laprun

Information and Communication Technologies (ICT) currently account for 3.4% of global green-house gas (GHG) emissions, or about 5.5 times those of France. These emissions, driven by the energy demands of applications and the infrastructure that they require, keep increasing. For ICT companies to decrease their emissions, developers need to be involved so that the energy consumption of applications can be taken into account as early as possible in a software's lifecycle.

To explore this problem space, bridging software engineering and sustainability, we created an experimental extension for the Quarkus framework, a major Java framework known for its developer experience focus, and an associated energy measuring harness. This article describes this extension along with some of the challenges we encountered and perspectives for future development.

Measure to act

Considering the non-negligible share of ICT companies in global GHG emissions, any reduction that these companies can achieve is very likely going to have a positive impact. While there are a multitude of levers that a company could activate to reduce its footprint, some more significant than others, this article focuses on the issue of reducing the energy consumption of software applications.

To reduce energy requirements, you first need to measure how much of it is being consumed. You also need to delimit the scope of exploration, as the topic is quite vast.

Starting from the observation that software is easier and cheaper to modify when changes are done early in its lifecycle, the focus needs to be on empowering developers to make energy-aware decisions as the application is being designed. This is in line with the "shift left" and DevOps approaches where developers are involved with the operational aspects of the application they work on. If you reduce the energy consumption of applications locally while developing them, you should see some form of these reductions when applications run in production as well. Energy efficiency is another facet of optimization, with some caveats, of course.

We initially focused on the CPU, instead of trying to track down all power consumption sources, a tradeoff to keep the initial implementation simple to validate the architecture before attempting to go further. When information from other sources is available, we took it into account, though.

Requirements for a developer-oriented software power-meter

Based on this simplified scope, what do developers need in a software power-meter?

The power-meter needs to:

  • Accurately measure energy (power) consumption at the process level at a minimum, but ideally down to the method, function, or code block level.
  • Be statistically relevant so that the results can be used to measure progress or lack thereof.
  • Have a negligible impact on the measurements and avoid disrupting the observation.
  • Be platform independent.
  • Provide a great developer experience and fit into their workflow, otherwise they just won't use it.
  • Ideally, integrate seamlessly with observability and profiling stacks.

The power-meter needs to record measures in such a way that developers can go back and look at historical data to extrapolate trends and measure progress independently of transient variations. For that purpose, it needs to be able to record measures for a given application version but also possibly variations thereof, such that it can test the impact of different implementations.

There are multiple software power-meters available, and new ones continue to emerge as research in this topic progresses. See, for example, the paper, "An experimental comparison of software-based power meters: focus on CPU and GPU", for a comparison of existing tools. For our purpose, however, when we started developing this extension, there was no tool that fulfill the requirements listed above. We initially considered, and even contributed a macOS backend to, JoularJX. However, we deemed, at the time, the agent approach not suitable for our purpose, since it would run in the same VM process as the monitored application, thus impacting the measure.

Enter quarkus-power, an energy-aware Quarkus extension

Quarkus is a well-known Java application framework that emphasizes efficiency and developer experience. The framework naturally becomes a target for experimentation in this space.

Using extensions, developers can hook into Quarkus' build system and runtime facilities to provide additional functionality. Quarkus enables application developers to live code their applications using its dedicated Dev mode. The Quarkus Dev UI is the visible part of the Dev mode, providing a dashboard of sorts to inspect different aspects of the application. Since Quarkus extension can augment this dashboard to provide additional information, developing an extension to display the energy consumption of the associated application in the Dev UI felt natural. This is exactly what the quarkus-power Quarkus extension does.

Design of the quarkus-power extension

The quarkus-power Quarkus extension allows developers to start and stop measures to minimize the disruption of the developer's workflow. Also, the extension provides a @PowerMeasure annotation that developers can add to their classes or methods to instruct the extension to scope the measure to that specific element.

After adding the quarkus-power extension to their Quarkus project, developers have access to an energy dashboard for their application. It initially provides two different views: one to control starting, stopping, and displaying the measures for the whole application and another one to see measures scoped by the @PowerMeasure annotation.

The first view has currently only minimal functionality and provides a simple way to interact with the measuring system, showing its metadata, along with color-coded energy measures as shown in the following figure:

Dev UI component to start and display power measures

The color coding depends on the relative power consumption of the application. In this example, we started the more intensive computations about midway through the measures and the display bars reflect that, turning red from green. We used the following code, triggered from a web application:

@PowerMeasure(name = "fibonacci")
int fibonacci(int n) {
    return fib(n);
}

static int fib(int n) {
    if (n <= 1) return n;
    return fib(n - 1) + fib(n - 2);
}

Since the fibonacci method is annotated with @PowerMeasure, the extension also computes the energy consumption attributed to each of this method's execution. These measures are shown in the extension's second view:

Showing power consumption for annotated methods

The UI is quite simple at this point and there's a good reason for this. One central aspect that we haven't addressed yet is how the extension gets the energy consumption measures. Let's look into that aspect and the consequences its implementation has on the design of the extension.

Measuring backend

The quarkus-power extension follows a server-oriented architecture: the server creates an abstraction layer on top of the hardware and provides a platform-independent, consistent view of the measures. Using a server separates the monitoring software from the monitored application, making it easier to measure.

The server publishes metadata about the available platform sensors and streams measures as they come in. The metadata allows client software (such as the quarkus-power extension) to make sense of the streamed data. The data is intentionally kept as minimal as possible to limit the impact to the measure. The server is a REST implementation, following established standards, which makes it easy for client applications to connect to the power measuring server, thus enabling a wide variety of applications, in a language-agnostic and framework-agnostic way.

This server is implemented by the power-server project, which is a Quarkus application. While choosing Java for this endeavor might be surprising, the language and its JVM are quite energy-efficient, according to a comparison of the energy efficiency of programming languages. Proficiency in Java also allowed us to get started quickly and iterate faster. Of course, we aim to be as efficient as possible, although heavy optimization hasn’t taken place at this point as we initially focused on ensuring data validity.

A multi-platform implementation

While the initial focus was on getting an end-to-end scenario working for the extension, it quickly became clear that the backend required a lot more work for the extension to be useful in the context of real applications. Also, ensuring the validity of the measures is a major challenge when attempting to create the very tools needed to take the measures. Efforts to get the power-server right and to develop a power command line interface (similar to the Linux time command but for energy consumption) caused us to pause the work on the quarkus-power extension (which now requires significant updates to adapt to the changes to the power-server).

From an architecture point of view, the hardware abstraction is realized by an API that represents a power sensor. This API is currently implemented for two platforms: Linux and macOS, which differ significantly. Providing a unified view of the data is a challenging problem, even without yet providing a Windows implementation! It is important to note that both platforms require elevated privileges to grant access to energy consumption information, which might prove to be an issue when attempting to run on constrained hardware.

macOS implementation

On macOS, power monitoring is performed using the bundled powermetrics tool. The powermetrics tool is high-level software, designed mostly for human consumption. It provides per-application energy consumption, along with overall consumption for the CPU, GPU, and Apple’s Neural Engine (Apple’s AI-focused chip). The tool works in a similar fashion on both Intel and Apple Silicon hardware.

While powermetrics provides all the information the power-server needs, consuming its output isn't trivial because it requires dispatching to an external process and parsing its rather complex output. Retrieving fine-grained energy consumption measures is paramount so power-server needs to drive powermetrics to provide timely information, which involves quite a bit of machinery to synchronize everything. Also, when running powermetrics that way, it suffers from some seemingly incompressible latency, thus preventing us from increasing the sampling frequency to get finer measures.

Linux implementation

On Linux, power monitoring is performed using Intel’s RAPL technology via the powercap framework. The provided information is organized under directories representing parts of the CPU architecture, each containing files representing how many micro-Joules were spent by that particular component since the counter was last reset. From these counters, the power-server computes power consumption. However, since the counters can overflow, the power-server has to account for this situation, which isn’t currently properly handled.

Contrary to the macOS implementation, this API is also only available for x86 architectures, so supporting ARM-based CPUs would require a different implementation. Moreover, the data gathered is provided at the system level, not the application one. Some work is therefore required to figure out which proportion of that consumption can actually be attributed to a specific application. If applications and measuring apparatus ran in the same JVM, we could get that data from the Java runtime. However, other scenarios (such as the aforementioned power command line interface) cannot benefit from that mechanism.

Summary

Working on power-server and the quarkus-power extension provides ongoing learning opportunities. Each backend seems to come with limitations, and while there are interesting leads to bypass these, doing so would require new approaches and significant rewriting. This article took stock of what has been accomplished and serves as a stepping stone before determining the next steps.

In the meantime, the software power-meter ecosystem has evolved, with new and existing updated tools that better align with the stated goals, particularly for the measuring backend. Leveraging and contributing to these tools instead of persisting with a bespoke solution may be a viable path forward.

Because the ICT companies’ energy consumption is significant and growing, developers need to be part of the solution and account for this aspect as they develop their applications. Reducing GHG emissions in this way can potentially lead to significant monetary savings. And, companies implementing such measures often derive secondary benefits, such as better brand image and competitive advantage. Finally, users also benefit because lower resource requirements to run the software often result in better usability and inclusivity by allowing a wider population to access the software.

While things are still very much experimental and rough around the edges, feedback on these projects is welcome to help shape their future. Give these projects (power-server and quarkus-power) a try and don't hesitate to open issues on the associated repositories!