Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JoularJX does not save the energy consumption data for the java code running for JMH becnchmark. #64

Open
ankitkumarsindhu opened this issue Feb 22, 2024 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@ankitkumarsindhu
Copy link

I have been running some test on java code with JMH and getting the details of energy consumption with JoularJX but for a specifc example it does not record the energy consumption details for anything instead it creates the similar folder structure as it creates for any test running with Joular, and the total-method energy file is empty even though the number of forks are set to 5 and the measurement iterations are 15.
The sample I am using:

  • It uses vectorized operations to add and multiply two arrays of integers.
  • Uses the jdk.incubator.vector package to do vector operations.

Is it because of vector operations used in the sample code? or something else.

Sample:
@benchmark
@WarmUp(iterations = 4)
@measurement(iterations = 6)
@BenchmarkMode({ Mode.AverageTime })
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@fork(jvmArgs = "--add-modules=jdk.incubator.vector", value = 2)
public void testVectorMultiply(ArraysState state, Blackhole blackhole) {
int[] result2 = multiply(state.a, state.b);
blackhole.consume(result2);
}

private static int[] multiply(int[] array1, int[] array2) {
    int[] multiplication = new int[array1.length];
    int vectorSize = SPECIES.length();
    int vectorCount = array1.length / vectorSize;
    for (int i = 0; i < vectorCount; i++) {
        IntVector vector1 = IntVector.fromArray(SPECIES, array1, i * vectorSize);
        IntVector vector2 = IntVector.fromArray(SPECIES, array2, i * vectorSize);
        IntVector resultVector = vector1.mul(vector2);
        resultVector.intoArray(multiplication, i * vectorSize);
    }
    // Perform remaining scalar multiplication
    for (int i = vectorCount * vectorSize; i < array1.length; i++) {
        multiplication[i] = array1[i] * array2[i];
    }
    return multiplication;
}
@adelnoureddine
Copy link
Member

Could you provide me with a minimal working example (a jar for instance), I can test on my machine?

We had issues in some cases where the monitoring loop for JoularJX ends prematurely, and therefore no energy data are recorded. It's mostly in some application servers as JoularJX tries to destroy the VM on shutdown.
The tentative fix (in issue #42) ended up with side effects on regular Java applications where the loop never ends.
You could try to apply that change (commit 1dd0a64) and see if that fix your issue.

@adelnoureddine adelnoureddine self-assigned this Feb 23, 2024
@adelnoureddine adelnoureddine added the bug Something isn't working label Feb 23, 2024
@ankitkumarsindhu
Copy link
Author

Hi! Below is the working example:

import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OutputTimeUnit;

import jdk.incubator.vector.IntVector;
import jdk.incubator.vector.VectorSpecies;

/**

  • This class demonstrates vectorized operations on arrays and measures their

  • execution time.
    */
    public class VectorOperations1 {

    private static final VectorSpecies SPECIES = IntVector.SPECIES_PREFERRED;

    @State(Scope.Benchmark)
    public static class ArraysState {
    int[] a;
    int[] b;

     @Setup(Level.Trial)
     public void setUp() {
         // Initialize arrays with default values for demonstration
         a = new int[] { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765 };
         b = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
     }
    

    }

    @benchmark
    @WarmUp(iterations = 4)
    @measurement(iterations = 6)
    @BenchmarkMode({ Mode.AverageTime, Mode.Throughput })
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    @fork(jvmArgs = "--add-modules=jdk.incubator.vector", value = 2)
    public void testVectorAdd(ArraysState state, Blackhole blackhole) {
    long startTime = System.nanoTime(); // Record start time
    int[] result1 = add(state.a, state.b);
    long endTime = System.nanoTime(); // Record end time
    long elapsedTime = endTime - startTime; // Calculate elapsed time
    System.out.println("Time taken for execution vector1 addition: " + elapsedTime + " nanoseconds");
    blackhole.consume(result1);
    }

    @benchmark
    @WarmUp(iterations = 4)
    @measurement(iterations = 6)
    @BenchmarkMode({ Mode.AverageTime })
    @OutputTimeUnit(TimeUnit.MICROSECONDS)
    @fork(jvmArgs = "--add-modules=jdk.incubator.vector", value = 2)
    public void testVectorMultiply(ArraysState state, Blackhole blackhole) {
    long startTime = System.nanoTime(); // Record start time
    int[] result2 = multiply(state.a, state.b);
    long endTime = System.nanoTime(); // Record end time
    long elapsedTime = endTime - startTime; // Calculate elapsed time
    System.out.println("Time taken for execution vector1 multiplication: " + elapsedTime + " nanoseconds");
    blackhole.consume(result2);
    }

    /**

    • Adds two arrays element-wise using vectorized operations and measures the
    • execution time.
    • @param array1 The first input array.
    • @param array2 The second input array.
    • @return The resulting array after addition.
      */
      private static int[] add(int[] array1, int[] array2) {
      int[] addition = new int[array1.length];
      int vectorSize = SPECIES.length();
      int vectorCount = array1.length / vectorSize;
      for (int i = 0; i < vectorCount; i++) {
      IntVector vector1 = IntVector.fromArray(SPECIES, array1, i * vectorSize);
      IntVector vector2 = IntVector.fromArray(SPECIES, array2, i * vectorSize);
      IntVector resultVector = vector1.add(vector2);
      resultVector.intoArray(addition, i * vectorSize);
      }
      // Perform remaining scalar addition
      for (int i = vectorCount * vectorSize; i < array1.length; i++) {
      addition[i] = array1[i] + array2[i];
      }
      return addition;
      }

    /**

    • Multiplies two arrays element-wise using vectorized operations and measures
    • the execution time.
    • @param array1 The first input array.
    • @param array2 The second input array.
    • @return The resulting array after multiplication.
      */
      private static int[] multiply(int[] array1, int[] array2) {
      int[] multiplication = new int[array1.length];
      int vectorSize = SPECIES.length();
      int vectorCount = array1.length / vectorSize;
      for (int i = 0; i < vectorCount; i++) {
      IntVector vector1 = IntVector.fromArray(SPECIES, array1, i * vectorSize);
      IntVector vector2 = IntVector.fromArray(SPECIES, array2, i * vectorSize);
      IntVector resultVector = vector1.mul(vector2);
      resultVector.intoArray(multiplication, i * vectorSize);
      }
      // Perform remaining scalar multiplication
      for (int i = vectorCount * vectorSize; i < array1.length; i++) {
      multiplication[i] = array1[i] * array2[i];
      }
      return multiplication;
      }
      }

@adelnoureddine
Copy link
Member

Could you try the proposed fix in issue #66, in this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants