Discovering JoularJX#

Note

For this lab, you should work on the lab room PCs.

We use the JoularJX tool, restricted to machines equipped with an Intel processor, furthermore you need specific rights to access RAPL registers.

Objectives

This lab will allow you to discover the JoularJX tool. This tool has the particularity to measure power consumption of a Java application down to the granularity of a single method.

Introduction#

About JoularJX#

JoularJX is a Java-based agent for software power monitoring at the source code level which:

  • Monitors power consumption of each method at runtime;

  • Uses a Java agent, no source code instrumentation needed;

  • Uses Intel RAPL (powercap interface) for getting accurate power reading on GNU/Linux;

  • Provides real time power consumption of every method in the monitored program;

  • Provides total energy for every method on program exit.

JoularJX stores power data every second in CSV files and, at the end of the monitoring session, it displays the total energy consumption for the java process (in Joules).

JoularJX has a non negligible energy cost. Its objective is more to highlight the most energy-hungry methods than to measure a java program energy consumption.

How it works

This is done by

  • Monitoring CPU utilization every second for each Java thread. Power consumption is allocated accordingly to the percentage. As a consequence, the energy consumed by other processes is not included in the energy result. This is done only every second because it is a costly operation.

  • A second monitoring loop detects, for every thread, which method is currently being executed for every 10 milliseconds (by observing the first method in the thread stacktrace). Then power consumption is allocated statistically to each method.

Attention

In practice, this requires to run a program for at least several seconds to be able to measure its power consumption.

Methods that last less than 10ms may not be detected.

Organization of the lab#

This lab has two parts:

  • You will first measure the power consumption of a single class Java program.

  • You will then test an application composed of a package with several classes and experiment with measurements at the level of a package, a class or a method.

Initializations#

The whole lab will be done in the $HOME/ENV4101/DiscoverJoularJXLab directory. If it does not already exist, create the ENV4101 directory. Go to this directory.

mkdir -p $HOME/ENV4101 
cd $HOME/ENV4101

Activate the python environment#

In all the terminals used for this lab, activate the env4101 environment:

source $HOME/env4101/bin/activate

as described on the python installation page: Installations Python

Get the code#

Then download the code for this lab (click on the mouse right button) and store it in your ENV4101 directory:

or copy the following command on your terminal:

wget https://www-inf.telecom-sudparis.eu/COURS/cen/Mesures/DiscoverJoularJXLab.zip

Unzip the code

unzip DiscoverJoularJXLab.zip

Go to the DiscoverJoularJXLab directory.

cd DiscoverJoularJXLab

Part 1 - Single class Java program#

Go to the RayCastingSingleClass directory.

cd RayCastingSingleClass

Overview of RayCasting class#

The RayCasting.java file implements the RayCasting class. This class is a simplified version of a ray casting algorithm adapted from the Rosetta Java implementation[1]. Its purpose is to check wether a given point is inside or outside a polygon.

In our RayCasting class, the algorithm is tested for the following shapes: square,  squareHole, strange and hexagon

final static int[][] square = ; final static int[][] squareHole = ; final static int[][] strange = ; final static int[][] hexagon = ;

final static int[][][] shapes = {square, squareHole, strange, hexagon};

A loop with a variable number of iterations nb_iteration is used to modify the duration of the program and better detect the energy used.

for (int i=0; i < nb_iteration; i++){ for (int[][] shape : shapes) { for (double[] pnt : testPoints) contains(shape, pnt); } } }

Perform measurements#

The RayCasting.java file is composed by the main() method which parses the input argument nb_iteration. The argument represents the number of iterations to be performed in the main(). This number of iterations is used to modify the duration of the program.
Augmenting the duration of the program is necessary to obtain exploitable results with JoularJX.

Take a look at the source code RayCasting.java. The provided code does not print information at the execution of each loop. In this case, we recommend to request 10.000.000 iterations. If you remove the comments on the lines printing information, the execution will take more time and you can request a smaller number of iterations.

The more times we launch the program, and the more accurate will be the computation of the means and standard deviations. We suggest this number to be between 3 to 5 during this lab, but it depends on the speed of the device.

To launch the application with JoularJX, we have prepared a main.sh script, see the readme.md file. The command to run has the following form:

bash main.sh RayCasting <nb_iteration> <nb_launch> First compile the application:

javac *.java

Then, experiment with the provided version of the program that does not print any information at each loop. Make a try with the following input values:

bash main.sh RayCasting 10000000 3
  • If the line “Program consumed 0,00 joules” gets displayed, this means that the program was too short to make relevant power measurements. You then have to ask for a larger number of iterations.

  • If the graph is difficult to read (too many methods displayed), may be it is a good idea to filter by method. We will do it in the next steps.

2 CSV files are automatically generated by JoularJX for each launch of the program. Those file names contain the Process ID (PID) of the java virtual machine. They are kept in a subdirectory of the results directory named with the date and time of the experiment (e.g. results/23.09.21-14h48m29s/).

  • joularJX-PID-methods-energy.csv: total cumulated energy consumption for all methods, include the called methods time.

  • joularJX-PID-methods-energy-filtered.csv: total cumulated energy consumption of the filtered methods (no filtered method for this question).

You will get these files for each execution (the nb_launch argument of the main.sh script corresponds to the number of executions).

The collected data are concatenated to prepare the final graphs displayed at the end of the script.

The script produces one graph for each csv file :

  • The first graph with the total cumulated energy consumption for all methods (may be difficult to read when there are too many methods). Each method appears with its total mean time and standard deviation computed from all the executions.

    • Be careful the consumption, is counted only when the method is the first one in the stack trace execution:

      • e.g. if m1 calls m2: during m2, the consumption will be attributed to m2.

  • The second graph shows only filtered methods. This second graph is not produced in this part of the lab, it is the reason why you see this message No result in filtered methods, either there is no filter or the filtered methods duration may be too short, we will use the filtering feature of JoularJX in the next part of the lab.

    • Be careful, in this second graph, the consumption is counted for the first FILTERED method encountered while browsing the stack trace from its top.

      • e.g. if m1 is filtered and m1 calls m2, the method for which the consumption will be counted during m2 depends on the fact that m2 is or not filtered.

      • If m2 is a filtered method, it will be counted for m2,

      • if m2 is not filtered, it will be counted for m1.

Attention

For each graph, the method consumption is counted for only one method.

  • In the case of the non filtered graph, it is counted for the active method only.

  • In the case of the filtered graph it is counted for the first filtered and active method encountered in the stack trace.

Share your results

All along the lab, you will have to fill a questionnaire. It is to be returned on moodle at the end of the lab. The questionnaire is in the markdown format. You can edit the Questionnaire with the following command:

ghostwriter Questionnaire.txt &

Experiment with filtering#

Initially, no filtering is performed, and the csv file produced for filtering is empty.

In this part of the lab, we will select the methods for which energy performance should be collected.

Filter configuration in config.properties file

Take a look at the config.properties file. It is a configuration file for JoularJX that describes which methods should be measured. This file contains the filter-method-names property to indicate JoularJX at which level the measurements should take place. If empty, no filtering will occur. The property may contain a list of filters, separated by commas. For a single class application like in this first step, the following filters may be used:

  • filter-method-names= \(\implies\) keep results for all methods from all invoked classes (even from JDK)

  • filter-method-names=Class1 \(\implies\) keep measures for all methods present in Class1

  • filter-method-names=Class1.methodA \(\implies\) keep measures for methodA of Class1

  • filter-method-names=Class1.methodA,Class1.methodB \(\implies\) keep measures for methodA and methodB of Class1

Be careful: no blank between two elements !

Modify the config.properties file to monitor only:

  1. The RayCasting class (i.e. filter all the methods of the class, RayCasting.main, RayCasting.contains and RayCasting.intersect)

  • filter-method-names=RayCasting

  1. The RayCasting.main method only

  • filter-method-names=RayCasting.main

  1. The RayCasting.main and the RayCasting.intersect methods

  • filter-method-names=RayCasting.main,RayCasting.intersect

This means that you have to change the config.properties file and then launch the above bash main.sh RayCasting 10000000 3 command again after each modification of the file. NB: You only change a configuration file, you don’t need to compile the java classes.

Question

  • How many methods are provided by the RayCasting class ? Do you see all the methods in the filtered diagram ? Why ?

NB: Some methods may be so short that JoularJX does not detect them: JoularJX gets method name (through execution stack trace) - every 10ms

Share your results

Do not forget to fill in the Questionnaire file for each modification of the config.properties file.

Specificities of JoularJX

For the filtered results, the data are not simply a subset of the non-filtered results. The data of a filtered method will include the energy consumed by the methods that it calls. For example, if package1.Class1.methodA calls java.io.PrintStream.println to print some text to a terminal, JoularJX then calculates:

  • In the first file (joularJX-PID-methods-energy.csv), the power or energy consumed by println separately from methodA. The latter power consumption will not include the power consumed by println.

  • In the second file (joularJX-PID-methods-energy-filtered.csv), if methods from package1 are filtered, then the power consumption of println will be added to methodA power consumption.

Measure the cost of displaying information on screen#

The method intersect does not consume much energy. In case it is not detected by JoularJX, it may not be shown on the graph. In this exercice, we will add a print call in this method, and see if it changes this method energy impact.

Warning

Make sure that your config.properties contains the line filter-method-names=RayCasting to select all the methods of the RayCasting class.

You have changed a java file, you need a new compilation

javac *.java

Modify the source code by uncommenting the line for printing information at each call. In the RayCasting.java file, uncomment the print line in the intersect method

            /*
                Uncomment the following line
                if you want to print results on the terminal.
                NB: This will take more time and energy.
            */
                System.out.print(""); 

Compile and launch a new series of experiment. Did it modify the result ?

Add the method java.io.PrintStream.print to the method filter, and explain the differences.

Share your results

Do not forget to fill in the Questionnaire file.

Part 2 - Java application in one package#

Go to the JavaCollectionsInOnePackage directory:

cd ../JavaCollectionsInOnePackage

Overview of the measureJavaCollections package#

Open the MeasureJavaCollections project in your favorite java development environment (e.g. eclipse). Then look at the 3 Java classes : Main, TestArrayList, TestLinkedList.

The measureJavaCollections package contains test classes with a name starting by Test (TestArrayList, TestLinkedList)to analyze the energy consumption of two basic Java collections:

  • ArrayList (Java Doc), a Resizable-array implementation

  • LinkedList (Java Doc), a Double-linked list implementation

Take time to remember the differences between those two implementations of the List interface.

Java collection test classes#

The test classes allow to test several methods to manipulate a collection. For each collection, there are methods to:

  • “add n elements” at the end of the collection (addElementsLinkedList, addElementsArrayList),

  • “access n elements” with their index varying from 0 to n (accessElementsLinkedList, accessElementsArrayList),

  • and finally methods to “remove n elements” taken at the end of the collection (removeElementsLinkedList, removeElementsArrayList).

Reflexion time

Take time to make your opinion on a hierarchy of the most consuming methods among the 6 above methods. Would it be the same hierarchy if we had done

  • “add n elements” at the beginning of the collection

  • “remove n elements” at the beginning of the collection

Main class#

The Main.java file contains the main() method which simply parses the input arguments to get the number of elements to store in the collections and then create the collections, add, access and remove elements in the two kinds of collections.

Perform measurements#

First compile the application:

javac measureJavaCollections/*.java

To launch the application with JoularJX, see the readme.md file. The command to launch has the following form:

bash main.sh measureJavaCollections.Main <number_of_elements_in_a_collection> <number_of_times_to_launch>

The higher number_of_times_to_launch is, the more times we launch the program, and the more accurate we are for making means and standard deviations.

Experiment with filtering#

Experiment for measuring the consumption of the different methods present in the package. Initially, no filtering is performed.

Then modify the config.properties files (See the explanations on the config.properties file in Part 1) to monitor:

  1. The measureJavaCollections package (that is all the methods of all the classes in the package)

  2. The measureJavaCollections.TestArrayList.addElementsArrayList,measureJavaCollections.TestLinkedList.addElementsLinkedList methods

  3. The measureJavaCollections.TestArrayList.accessElementsArrayList,measureJavaCollections.TestLinkedList.accessElementsLinkedList methods

  4. The measureJavaCollections.TestArrayList.removeElementsArrayList,measureJavaCollections.TestLinkedList.removeElementsLinkedList methods

After each modification of the config.properties file, launch the main.sh script.

NB: You may have to ADAPT the size of the collection according to your computer:

You may begin with a collection of 200000 elements and 1 run (to adapt the size of the collection for an acceptable duration time (below one minute) before augmenting the number of runs for a better standard deviation).

bash main.sh measureJavaCollections.Main 200000 2
  • REDUCE the collection size if the execution time is too high (e.g. above 1 min).

  • INCREASE the collection size if the energy is too low to be detectable.

Detect the most consuming method (e.g. TestLinkedList.accessElementsLinkedList), remove the call to this method from the Main class to reduce the execution time, and lauch the experiment again to be able to compare the other methods (NB: Do not remove the add method that is creating the collection !).

Analyze the different results obtained and try to identify what collection is the most energy-efficient in the following cases:

  1. To add elements (at the end of the collection),

  2. To access elements by their index,

  3. To remove elements (beginning at the end of the collection).

Verify your results and check whether you get the same results as in this catalog of good practices. Take this opportunity to explore the catalog as we will use it in the next lab.

Share your results

Do not forget to return on Moodle the Questionnaire file at the end of the Discover JoularJX lab (one file only).