Software Tuning, Performance Optimization & Platform Monitoring
Discussion around monitoring and software tuning methodologies, Performance Monitoring Unit (PMU) of Intel microprocessors, and platform monitoring
1636 Discussions

Linking the Intel Power Gadget API with the Java Native Interface

timerdar
Novice
547 Views

Hello Intel Community,

 

I am currently working on my master thesis project, where I want to (very coarsely) monitor the energy consumption behavior of several Java Benchmarks. I linked my Java Code with the Intel Power Gadget API via the Java Native Interface (JNI).

 

After I spent some time fixing some Java-side concurrency errors, I have now to deal with an error in the Intel Power Gadget API. And because the code is not open source, I hope you can help me with this problem.

 

The Code:

 

The C code is called from a Java Program. The control flow of the whole profiling mechanism is in the Java code, so the C code does only execute the statements to start logging, to reading samples and to stop logging.

 

Please don't feel confused by the nativeLog function. If I try to directly print out these messages via printf, the messages are all queued up until the end of all benchmarks and then printed. It's just a very hacky workaround.

 

Profiling_PowerGadgetProfiler.c:

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <IntelPowerGadget/EnergyLib.h>

#include "Profiling_PowerGadgetProfiler.h"

void nativeLog(JNIEnv *env, jclass thisClass, char message[]){
    jmethodID mid = (*env)->GetStaticMethodID(env, thisClass, "nativeLog", "(Ljava/lang/String;)V");

    if(mid != NULL)
    {
      jstring str = (*env)->NewStringUTF(env, message);
      (*env)->CallStaticVoidMethod(env, thisClass, mid, str);
    }
}

JNIEXPORT void JNICALL Java_Profiling_PowerGadgetProfiler_startProfiling
  (JNIEnv *env, jclass thisClass, jstring fileName)
  {
      IntelEnergyLibInitialize();

      nativeLog(env, thisClass, "NATIVE PROFILER INITIALIZED\n");
      char fileNameAsString[255];

      const char *fileNameAsConstString = (*env)->GetStringUTFChars(env, fileName, 0);

      strcpy(fileNameAsString, fileNameAsConstString);

      nativeLog(env, thisClass, "STARTING PROFILING IN NATIVE CODE\n");

      StartLog(fileNameAsString);
      nativeLog(env, thisClass, "LOGGING STARTED SUCCESSFULLY\n");
  }


JNIEXPORT void JNICALL Java_Profiling_PowerGadgetProfiler_readSample
  (JNIEnv *env , jclass thisClass)
{
    ReadSample();
}

JNIEXPORT void JNICALL Java_Profiling_PowerGadgetProfiler_stopProfiling
 (JNIEnv* env, jclass thisClass)
{
    nativeLog(env, thisClass, "ENDING PROFILING IN NATIVE CODE AND WRITE TO FILE\n");
    StopLog();
    nativeLog(env, thisClass, "LOGGING STOPPED SUCCESSFULLY\n");
}

 

The error:

The code fails during the execution of StopLog(). In the following image, you can see the stack trace: Bildschirmfoto 2021-12-11 um 15.22.44.png

 

Considerations:

  • Is the way or order I call these functions incorrect? 
  • In an early version of my program, the control flow was in the C program. There was just one function named startProfiling(), which was called and took care of initializing the profiler, starting logging, reading samples and stopping logging. There was a static variable which indicated the running state of a benchmark and while it was not set to 0, the program kept reading samples. So, do I have to call all of the functions in the same function like in the Intel Power Gadget API sample code?

 

I hope you can help me. Thank you for your patience.

0 Kudos
3 Replies
AndrewG_Intel
Moderator
514 Views

Hello @timerdar

Thank you for posting on the Intel® communities.


We understand that you have some inquiries related to Intel® Power Gadget API. We have a forum for those specific products and questions so we are moving it to the Software Tuning, Performance Optimization & Platform Monitoring Forum so it can get answered more quickly.


Best regards,

Andrew G.

Intel Customer Support Technician


timerdar
Novice
506 Views

Hello Andrew G,

 

for some reason, the post landed in the wrong section. But I thought I made sure that it is in the right topic. Even my notification mail said, that it was in the right topic. 

 

Bildschirmfoto 2021-12-16 um 21.49.49.png

Thank your for your help.

 

Best regards,

Tim Erdar

timerdar
Novice
498 Views

I solved the error by myself. The program failed because the sampling was too fast at a certain point of time. I applied the following changes to my program:

 

  • I moved the control flow of my benchmark back in my C code
  • I placed a sleep call after each `ReadSample()`

 

The updated program: 

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <IntelPowerGadget/EnergyLib.h>

#include "Profiling_PowerGadgetProfiler.h"

static int running = 0;

void nativeLog(JNIEnv *env, jclass thisClass, char message[]){
    jmethodID mid = (*env)->GetStaticMethodID(env, thisClass, "nativeLog", "(Ljava/lang/String;)V");

    if(mid != NULL)
    {
      jstring str = (*env)->NewStringUTF(env, message);
      (*env)->CallStaticVoidMethod(env, thisClass, mid, str);
    }
}

JNIEXPORT void JNICALL Java_Profiling_PowerGadgetProfiler_profileExecution
  (JNIEnv *env, jclass thisClass, jstring fileName)
  {
        running = 1;
        IntelEnergyLibInitialize();

        nativeLog(env, thisClass, "NATIVE PROFILER INITIALIZED\n");
        char fileNameAsString[255];

        const char *fileNameAsConstString = (*env)->GetStringUTFChars(env, fileName, 0);

        strcpy(fileNameAsString, fileNameAsConstString);

        nativeLog(env, thisClass, "STARTING PROFILING IN NATIVE CODE\n");

        StartLog(fileNameAsString);
        nativeLog(env, thisClass, "LOGGING STARTED SUCCESSFULLY\n");

        while(running)
        {
            ReadSample();
            usleep(1000);   // maybe there is an higher safe possible sampling rate
        }

        nativeLog(env, thisClass, "ENDING PROFILING IN NATIVE CODE AND WRITE TO FILE\n");
        StopLog();
        nativeLog(env, thisClass, "LOGGING STOPPED SUCCESSFULLY\n");
  }

JNIEXPORT void JNICALL Java_Profiling_PowerGadgetProfiler_stopProfiling
  (JNIEnv *env, jclass thisClass)
  {
    running = 0;
    nativeLog(env, thisClass, "NATIVE RUNNING FLAG IS SET TO FALSE\n");
  }

Finally, there only remains one last question. What is the highest possible sampling rate that can be achieved with ReadSample() without failing? Or is it possible to determine this sampling rate or minimum timeout?

 

Best regards,

Tim Erdar

Reply