Java Async Profiler Flame Graph

353 Views Asked by At

In the scenario below, is Java async-profiler the right tool to see where's time spent when comparing performance of ArrayBlockingQueue and LinkedBlockingQueue?

On my machine, total execution time of ABQ is always 25% faster than LBQ when sharing 50M entries between a consumer and a producer. Flame graphs of both are "pretty much" same except LBQ one shows only a handful of samples from JVM object allocation code but this wouldn't jusify 25% increase. As expected, TLAB allocation in LBQ is much higher.

I was wondering, how can I see which activity (be it code or hardware) is taking the time?

Runner:

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Runner {

    public static void main(String[] args) throws InterruptedException {


        int size = 50_000_000;
        BlockingQueue<Long> queue = new LinkedBlockingQueue<>(size);

        Producer producer = new Producer(queue, size);
        Thread t = new Thread(producer);
        t.setName("ProducerItIs");

        Consumer consumer = new Consumer(queue, size);
        Thread t2 = new Thread(consumer);
        t2.setName("ConsumerItIs");


        t.start();
        t2.start();

        Thread.sleep(8000);
        System.out.println("done");
        queue.forEach(System.out::println);
        System.out.println(queue.size());
    }
}

Producer:

import java.util.Queue;
import java.util.Random;
import java.util.concurrent.BlockingQueue;

public class Producer implements Runnable {

    public Producer(BlockingQueue<Long> blockingQueue, int size) {
        this.queue = blockingQueue;
        this.size = size;

    }

    private final BlockingQueue<Long> queue;
    private final int size;

    public void run() {

        System.out.println("Started to produce...");
        long nanos = System.nanoTime();
        Long ii = (long) new Random().nextInt();

        for (int j = 0; j < size; j++) {
                queue.add(ii);
        }
        System.out.println("producer Time taken :" + ((System.nanoTime() - nanos) / 1e6));
    }
}

Consumer:

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {

    private final BlockingQueue<Long> blockingQueue;
    private final int size;


    private Long value;

    public Consumer(BlockingQueue<Long> blockingQueue, int size) {
        this.blockingQueue = blockingQueue;
        this.size = size;
    }

    public void run() {
        long nanos = System.nanoTime();

        System.out.println("Starting to consume...");
        int i = 1;
        try {
            while (true) {
                value = blockingQueue.take();
                i++;

                if (i >= size) {
                    break;
                }

            }
            System.out.println("Consumer Time taken :" + ((System.nanoTime() - nanos)/1e6));
        } catch (Exception exp) {
            System.out.println(exp);
        }
    }
    public long getValue() {
        return value;
    }
}

With ArrayBlockingQueue: enter image description here

With LinkedListBlockedQueue: Black arrow showing samples captured for allocations enter image description here

0

There are 0 best solutions below