From heinz at javaspecialists.eu Thu Oct 31 20:59:10 2024 From: heinz at javaspecialists.eu (Dr Heinz M. Kabutz) Date: Thu, 31 Oct 2024 22:59:10 +0200 Subject: Fun with Spliterators Message-ID: <6c496214-5a12-40ea-a58e-628ced5341bb@javaspecialists.eu> Hi Doug, I've been looking at the spliterators in the LBQ and other concurrent classes. I'm aware that the likelihood of anyone ever wanting to parallel stream over one of these is extremely remote, so this is just a curiosity. In my experiment, I create 10m * hardware threads elements and put them into various collections. I then parallel stream over them and count how many times each thread executes is used. Not surprisingly, the ArrayList does very well, since it is based on a sized and subsized array. Some of the other collections were a bit surprising. Since I'm busy looking at the LBQ at the moment, here are its results: LinkedBlockingQueue ForkJoinPool.commonPool-worker-1=22242736 185.36% ForkJoinPool.commonPool-worker-11=406 0.00% ForkJoinPool.commonPool-worker-2=8169 0.07% ForkJoinPool.commonPool-worker-3=23194669 193.29% ForkJoinPool.commonPool-worker-4=22421660 186.85% ForkJoinPool.commonPool-worker-5=79 0.00% ForkJoinPool.commonPool-worker-6=24577826 204.82% ForkJoinPool.commonPool-worker-7=27462223 228.85% ForkJoinPool.commonPool-worker-9=92230 0.77% main=2 0.00% time = 985ms We see that LBQ's parallel stream only used 10/12 cores and almost all the work was done by 5 threads. In contrast, ArrayList: ArrayList ForkJoinPool.commonPool-worker-1=11250000 112.50% ForkJoinPool.commonPool-worker-10=9375000 93.75% ForkJoinPool.commonPool-worker-11=11250000 112.50% ForkJoinPool.commonPool-worker-2=7500000 75.00% ForkJoinPool.commonPool-worker-3=9375000 93.75% ForkJoinPool.commonPool-worker-4=9375000 93.75% ForkJoinPool.commonPool-worker-5=11250000 112.50% ForkJoinPool.commonPool-worker-6=11250000 112.50% ForkJoinPool.commonPool-worker-7=9375000 93.75% ForkJoinPool.commonPool-worker-8=7500000 75.00% ForkJoinPool.commonPool-worker-9=11250000 112.50% main=11250000 112.50% time = 287ms This is, of course, not surprising, given the linked vs array based nature of the collections. Here is my code for your amusement: import java.util.*; import java.util.concurrent.*; import java.util.function.*; import java.util.stream.*; public class LinkedBlockingQueueSpliterating { ??? private static int ELEMENTS = ??????????? 10_000_000 * Runtime.getRuntime().availableProcessors(); ??? public static void main(String... args) { ??????? test(new ArrayBlockingQueue<>(ELEMENTS)); ??????? test(new ArrayList<>()); ??????? test(new LinkedList<>()); ??????? test(new LinkedBlockingQueue<>()); ??????? test(new ConcurrentLinkedQueue<>()); ??????? test(new ConcurrentLinkedDeque<>()); ??????? test(new ArrayDeque<>()); ??? } ??? private static void test(Collection collection) { ??????? System.out.println(collection.getClass().getSimpleName()); ??????? for (int i = 0; i < ELEMENTS; i++) { ??????????? collection.add(i); ??????? } ??????? long time = System.nanoTime(); ??????? try { ??????????? Map tasksPerThread = ??????????????????? collection.parallelStream() ??????????????????????????? .map(i -> Thread.currentThread().getName()) ??????????????????????????? .collect(Collectors.groupingBy( ??????????????????????????????????? Function.identity(), ??????????????????????????????????? TreeMap::new, ??????????????????????????????????? Collectors.counting() ??????????????????????????? )); ??????????? int expectedTasksPerThread = collection.size() / tasksPerThread.size(); ??????????? for (var entry : tasksPerThread.entrySet()) { ??????????????? System.out.printf("%s %.2f%%%n", entry, ??????????????????????? 100.0 * entry.getValue() / expectedTasksPerThread); ??????????? } ??????? } finally { ??????????? time = System.nanoTime() - time; ??????????? System.out.printf("time = %dms%n%n", (time / 1_000_000)); ??????? } ??? } } Regards Heinz -- Dr Heinz M. Kabutz (PhD CompSci) Author of "The Java? Specialists' Newsletter" - www.javaspecialists.eu Java Champion - www.javachampions.org JavaOne Rock Star Speaker Tel: +30 69 75 595 262 Skype: kabutz