From daa59c0fed3178b97ece260f57f49e4c747f3190 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Sun, 5 Oct 2025 14:20:57 +0000 Subject: [PATCH 01/12] Setting up GitHub Classroom Feedback From 69d1e399d103153605864a32e2e0d8a8bc0cbdbb Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Sun, 5 Oct 2025 14:20:59 +0000 Subject: [PATCH 02/12] add deadline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6495c30..0eb4312 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/AwTYhPar) # Лабораторная работа № 1: определение достижимости параллелизма и реализация параллельных алгоритмов. Шаги выполнения: From c0a733df205f965cde5485ef1b5a9b58d0b54c87 Mon Sep 17 00:00:00 2001 From: DaniilStepanov Date: Sun, 28 Sep 2025 13:57:01 +0300 Subject: [PATCH 03/12] new random graph generation algorithm --- tmp/results.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmp/results.txt b/tmp/results.txt index 027e7f9..511eda5 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -3,11 +3,11 @@ Serial: 0 Parallel: 0 -------- Times for 100 vertices and 500 connections: -Serial: 0 +Serial: 1 Parallel: 0 -------- Times for 1000 vertices and 5000 connections: -Serial: 1 +Serial: 0 Parallel: 0 -------- Times for 10000 vertices and 50000 connections: From f39e7a2bbf38b6db4c2e0c73cd5086c6a9c85ed0 Mon Sep 17 00:00:00 2001 From: DaniilStepanov Date: Mon, 29 Sep 2025 22:45:19 +0300 Subject: [PATCH 04/12] readme update --- tmp/results.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmp/results.txt b/tmp/results.txt index 511eda5..027e7f9 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -3,11 +3,11 @@ Serial: 0 Parallel: 0 -------- Times for 100 vertices and 500 connections: -Serial: 1 +Serial: 0 Parallel: 0 -------- Times for 1000 vertices and 5000 connections: -Serial: 0 +Serial: 1 Parallel: 0 -------- Times for 10000 vertices and 50000 connections: From 5905651a2067a9d7dd76e6037880782147265da2 Mon Sep 17 00:00:00 2001 From: DaniilStepanov Date: Wed, 1 Oct 2025 10:30:58 +0300 Subject: [PATCH 05/12] RandomGraphGenerator fix --- build.gradle.kts | 21 ++++++++- src/main/java/org/itmo/UnsafeCounter.java | 13 ++++++ .../java/org/itmo/RandomGraphGenerator.java | 45 ++++++++++++++++--- src/test/java/org/itmo/UnsafeCounterTest.java | 27 +++++++++++ 4 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/itmo/UnsafeCounter.java create mode 100644 src/test/java/org/itmo/UnsafeCounterTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 3341beb..5370e10 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("jvm") version "1.9.20" + java application } @@ -12,6 +13,8 @@ repositories { dependencies { testImplementation(kotlin("test")) + testImplementation("org.openjdk.jcstress:jcstress-core:0.16") + testAnnotationProcessor("org.openjdk.jcstress:jcstress-core:0.16") } tasks.test { @@ -24,4 +27,20 @@ kotlin { application { mainClass.set("MainKt") -} \ No newline at end of file +} + +// JCStress runner task: runs JCStress tests located on the test runtime classpath +// Use: ./gradlew jcstress [-PjcstressArgs="-v -m quick"] +tasks.register("jcstress") { + group = "verification" + description = "Run JCStress stress tests" + mainClass.set("org.openjdk.jcstress.Main") + classpath = sourceSets.test.get().runtimeClasspath + dependsOn("testClasses") + + val argsProp = project.findProperty("jcstressArgs") as String? + if (!argsProp.isNullOrBlank()) { + args = argsProp.split("\\s+".toRegex()) + } +} + diff --git a/src/main/java/org/itmo/UnsafeCounter.java b/src/main/java/org/itmo/UnsafeCounter.java new file mode 100644 index 0000000..1041a21 --- /dev/null +++ b/src/main/java/org/itmo/UnsafeCounter.java @@ -0,0 +1,13 @@ +package org.itmo; + +public class UnsafeCounter { + private int counter = 0; + + public void increment() { + counter++; // <-- гонка данных + } + + public int get() { + return counter; + } +} diff --git a/src/test/java/org/itmo/RandomGraphGenerator.java b/src/test/java/org/itmo/RandomGraphGenerator.java index fdb888c..1a57226 100644 --- a/src/test/java/org/itmo/RandomGraphGenerator.java +++ b/src/test/java/org/itmo/RandomGraphGenerator.java @@ -1,7 +1,9 @@ package org.itmo; import java.util.Arrays; +import java.util.HashSet; import java.util.Random; +import java.util.Set; import java.util.SplittableRandom; import java.util.concurrent.ForkJoinPool; import java.util.stream.IntStream; @@ -11,22 +13,27 @@ public class RandomGraphGenerator { private long pack(int u, int v) { return (((long) u) << 32) | (v & 0xffffffffL); } + private int unpackU(long key) { return (int) (key >>> 32); } + private int unpackV(long key) { return (int) (key & 0xffffffffL); } Graph generateGraph(Random r, int size, int numEdges) { + if (size < 1) throw new IllegalArgumentException("size must be >= 1"); if (numEdges < size - 1) throw new IllegalArgumentException("We need min size-1 edges"); long maxDirected = (long) size * (size - 1); if (numEdges > maxDirected) throw new IllegalArgumentException("Too many edges for directed graph without self-loops"); - int[] perm = java.util.stream.IntStream.range(0, size).toArray(); - for (int i = size - 1; i > 1; i--) { - int j = 1 + r.nextInt(i); - int tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp; + int[] perm = IntStream.range(0, size).toArray(); + for (int i = size - 1; i > 0; i--) { + int j = r.nextInt(i + 1); + int tmp = perm[i]; + perm[i] = perm[j]; + perm[j] = tmp; } final int chainCount = size - 1; @@ -74,7 +81,7 @@ Graph generateGraph(Random r, int size, int numEdges) { while (unique < numEdges) { int missing = numEdges - unique; - int extra = Math.max(missing / 2, 10_000); // небольшой запас + int extra = Math.max(missing / 2, 10_000); int add = missing + extra; long[] more = new long[unique + add]; @@ -109,6 +116,31 @@ Graph generateGraph(Random r, int size, int numEdges) { keys = more; } + Set chainSet = new HashSet<>(chainCount * 2); + for (int i = 1; i < size; i++) { + chainSet.add(pack(perm[i - 1], perm[i])); + } + + int p = 0; + for (int i = 0; i < unique && p < chainCount; i++) { + long e = keys[i]; + if (chainSet.remove(e)) { + // swap keys[p] и keys[i] + long tmp = keys[p]; + keys[p] = keys[i]; + keys[i] = tmp; + p++; + } + } + + SplittableRandom shuf = base.split(); + for (int i = p; i < numEdges; i++) { + int j = i + shuf.nextInt(unique - i); + long tmp = keys[i]; + keys[i] = keys[j]; + keys[j] = tmp; + } + Graph g = new Graph(size); for (int i = 0; i < numEdges; i++) { long key = keys[i]; @@ -118,5 +150,4 @@ Graph generateGraph(Random r, int size, int numEdges) { } return g; } - -} +} \ No newline at end of file diff --git a/src/test/java/org/itmo/UnsafeCounterTest.java b/src/test/java/org/itmo/UnsafeCounterTest.java new file mode 100644 index 0000000..a831605 --- /dev/null +++ b/src/test/java/org/itmo/UnsafeCounterTest.java @@ -0,0 +1,27 @@ +package org.itmo; + +import org.openjdk.jcstress.annotations.*; +import org.openjdk.jcstress.infra.results.I_Result; + +@JCStressTest +@Outcome(id = "5", expect = Expect.ACCEPTABLE, desc = "Все 5 инкрементов выполнены корректно") +@Outcome(id = "1", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@Outcome(id = "2", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@Outcome(id = "3", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@Outcome(id = "4", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@State +public class UnsafeCounterTest { + + private UnsafeCounter counter = new UnsafeCounter(); + + @Actor public void actor1() { counter.increment(); } + @Actor public void actor2() { counter.increment(); } + @Actor public void actor3() { counter.increment(); } + @Actor public void actor4() { counter.increment(); } + @Actor public void actor5() { counter.increment(); } + + @Arbiter + public void arbiter(I_Result r) { + r.r1 = counter.get(); + } +} From 3dbb7a6308952dfc3410dbb2fac28effd6aba7ec Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 11:44:24 +0000 Subject: [PATCH 06/12] Initial commit --- .../java/org/itmo/RandomGraphGenerator.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/test/java/org/itmo/RandomGraphGenerator.java b/src/test/java/org/itmo/RandomGraphGenerator.java index 1a57226..3f02e49 100644 --- a/src/test/java/org/itmo/RandomGraphGenerator.java +++ b/src/test/java/org/itmo/RandomGraphGenerator.java @@ -23,10 +23,13 @@ private int unpackV(long key) { } Graph generateGraph(Random r, int size, int numEdges) { - if (size < 1) throw new IllegalArgumentException("size must be >= 1"); - if (numEdges < size - 1) throw new IllegalArgumentException("We need min size-1 edges"); + if (size < 1) + throw new IllegalArgumentException("size must be >= 1"); + if (numEdges < size - 1) + throw new IllegalArgumentException("We need min size-1 edges"); long maxDirected = (long) size * (size - 1); - if (numEdges > maxDirected) throw new IllegalArgumentException("Too many edges for directed graph without self-loops"); + if (numEdges > maxDirected) + throw new IllegalArgumentException("Too many edges for directed graph without self-loops"); int[] perm = IntStream.range(0, size).toArray(); for (int i = size - 1; i > 0; i--) { @@ -34,6 +37,7 @@ Graph generateGraph(Random r, int size, int numEdges) { int tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp; + } final int chainCount = size - 1; @@ -55,7 +59,8 @@ Graph generateGraph(Random r, int size, int numEdges) { final SplittableRandom base = new SplittableRandom(r.nextLong()); final SplittableRandom[] seeds = new SplittableRandom[threads]; - for (int t = 0; t < threads; t++) seeds[t] = base.split(); + for (int t = 0; t < threads; t++) + seeds[t] = base.split(); long[] finalKeys = keys; IntStream.range(0, threads).parallel().forEach(t -> { @@ -65,7 +70,8 @@ Graph generateGraph(Random r, int size, int numEdges) { for (int i = start; i < end; i++) { int u = rnd.nextInt(size); int v = rnd.nextInt(size - 1); - if (v >= u) v++; + if (v >= u) + v++; finalKeys[i] = pack(u, v); } }); @@ -89,7 +95,8 @@ Graph generateGraph(Random r, int size, int numEdges) { final SplittableRandom base2 = base.split(); final SplittableRandom[] seeds2 = new SplittableRandom[threads]; - for (int t = 0; t < threads; t++) seeds2[t] = base2.split(); + for (int t = 0; t < threads; t++) + seeds2[t] = base2.split(); final int offset2 = unique; final int chunk2 = (add + threads - 1) / threads; @@ -100,7 +107,8 @@ Graph generateGraph(Random r, int size, int numEdges) { for (int i = start; i < end; i++) { int u = rnd.nextInt(size); int v = rnd.nextInt(size - 1); - if (v >= u) v++; + if (v >= u) + v++; more[i] = pack(u, v); } }); @@ -150,4 +158,5 @@ Graph generateGraph(Random r, int size, int numEdges) { } return g; } -} \ No newline at end of file + +} From 5b818118ac54a47655e16d3f4f557d6b473ab6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=94=D0=B0=D0=B2?= =?UTF-8?q?=D1=8B=D0=B4=D0=BE=D0=B2?= Date: Mon, 6 Oct 2025 23:33:42 +0300 Subject: [PATCH 07/12] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20QueueBalancer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/itmo/QueueBalancer.java | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/org/itmo/QueueBalancer.java diff --git a/src/main/java/org/itmo/QueueBalancer.java b/src/main/java/org/itmo/QueueBalancer.java new file mode 100644 index 0000000..c961549 --- /dev/null +++ b/src/main/java/org/itmo/QueueBalancer.java @@ -0,0 +1,26 @@ +package org.itmo; + +import java.util.ArrayDeque; +import java.util.List; +import java.util.Queue; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class QueueBalancer { + private Integer nextQueue; + private final List> queues; + + QueueBalancer(Integer size) { + nextQueue = 0; + queues = Stream.>generate(ArrayDeque::new).limit(size).collect(Collectors.toList()); + } + + void add(T value) { + nextQueue = (nextQueue + 1) % queues.size(); + queues.get(nextQueue).add(value); + } + + List> getQueues() { + return queues; + } +} From f046e560714b8f60ff6ac10d231a22c6be4b69c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=94=D0=B0=D0=B2?= =?UTF-8?q?=D1=8B=D0=B4=D0=BE=D0=B2?= Date: Mon, 6 Oct 2025 23:33:52 +0300 Subject: [PATCH 08/12] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BB=D0=BB=D0=B5=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20bfs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/itmo/Graph.java | 58 +++++++++++++++++++++++++++-- src/test/java/org/itmo/BFSTest.java | 10 ++--- tmp/results.txt | 30 ++++++++------- 3 files changed, 75 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index 141a0b6..c9ffe34 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -1,13 +1,18 @@ package org.itmo; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collector; +import java.util.stream.Collectors; class Graph { private final int V; private final ArrayList[] adjList; + private final ExecutorService executor; Graph(int vertices) { this.V = vertices; @@ -15,6 +20,8 @@ class Graph { for (int i = 0; i < vertices; ++i) { adjList[i] = new ArrayList<>(); } + + executor = Executors.newFixedThreadPool(12); } void addEdge(int src, int dest) { @@ -24,9 +31,54 @@ void addEdge(int src, int dest) { } void parallelBFS(int startVertex) { + AtomicBoolean[] visited = new AtomicBoolean[V]; + for (Integer i = 0; i < V; i++) { + visited[i] = new AtomicBoolean(false); + } + + QueueBalancer balancer = new QueueBalancer<>(12); + Queue nextVertexes = new ConcurrentLinkedQueue<>(); + + visited[startVertex].set(true); + nextVertexes.add(startVertex); + + Boolean hasVertextsToProcess = true; + + while (hasVertextsToProcess) { + while (!nextVertexes.isEmpty()) { + balancer.add(nextVertexes.poll()); + } + + hasVertextsToProcess = balancer.getQueues().stream() + .map((queue) -> executor.submit(() -> { + if (queue.isEmpty()) { + return false; + } + + while (!queue.isEmpty()) { + Integer vertex = queue.poll(); + + for (int n : adjList[vertex]) { + Boolean isVisited = visited[n].getAndSet(true); + if (!isVisited) { + nextVertexes.add(n); + } + } + } + + return true; + })).map((future) -> { + try { + return future.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + return false; + } + }).reduce(hasVertextsToProcess, (acc, futureResult) -> acc && futureResult); + } } - //Generated by ChatGPT + // Generated by ChatGPT void bfs(int startVertex) { boolean[] visited = new boolean[V]; diff --git a/src/test/java/org/itmo/BFSTest.java b/src/test/java/org/itmo/BFSTest.java index 7bf9098..77af020 100644 --- a/src/test/java/org/itmo/BFSTest.java +++ b/src/test/java/org/itmo/BFSTest.java @@ -4,18 +4,15 @@ import java.io.FileWriter; import java.io.IOException; -import java.nio.Buffer; -import java.util.HashSet; +import java.util.List; import java.util.Random; -import java.util.function.BiFunction; -import java.util.stream.IntStream; public class BFSTest { @Test public void bfsTest() throws IOException { - int[] sizes = new int[]{10, 100, 1000, 10_000, 10_000, 50_000, 100_000, 1_000_000, 2_000_000}; - int[] connections = new int[]{50, 500, 5000, 50_000, 100_000, 1_000_000, 1_000_000, 10_000_000, 10_000_000}; + int[] sizes = new int[] { 10, 100, 1000, 10_000, 10_000, 50_000, 100_000, 1_000_000, 2_000_000 }; + int[] connections = new int[] { 50, 500, 5000, 50_000, 100_000, 1_000_000, 1_000_000, 10_000_000, 10_000_000 }; Random r = new Random(42); try (FileWriter fw = new FileWriter("tmp/results.txt")) { for (int i = 0; i < sizes.length; i++) { @@ -34,7 +31,6 @@ public void bfsTest() throws IOException { } } - private long executeSerialBfsAndGetTime(Graph g) { long startTime = System.currentTimeMillis(); g.bfs(0); diff --git a/tmp/results.txt b/tmp/results.txt index 027e7f9..0d0bfaf 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,32 +1,36 @@ Times for 10 vertices and 50 connections: Serial: 0 -Parallel: 0 +Parallel: 3 -------- Times for 100 vertices and 500 connections: Serial: 0 -Parallel: 0 +Parallel: 1 -------- Times for 1000 vertices and 5000 connections: -Serial: 1 -Parallel: 0 +Serial: 0 +Parallel: 2 -------- Times for 10000 vertices and 50000 connections: Serial: 3 -Parallel: 0 +Parallel: 1 -------- Times for 10000 vertices and 100000 connections: -Serial: 2 -Parallel: 0 +Serial: 1 +Parallel: 2 -------- Times for 50000 vertices and 1000000 connections: -Serial: 30 -Parallel: 0 +Serial: 17 +Parallel: 4 -------- Times for 100000 vertices and 1000000 connections: -Serial: 18 -Parallel: 0 +Serial: 12 +Parallel: 2 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 307 -Parallel: 0 +Serial: 625 +Parallel: 285 +-------- +Times for 2000000 vertices and 10000000 connections: +Serial: 1019 +Parallel: 301 -------- From ac3064958b103ac702e606861a75d319560a390c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=94=D0=B0=D0=B2?= =?UTF-8?q?=D1=8B=D0=B4=D0=BE=D0=B2?= Date: Tue, 7 Oct 2025 00:05:14 +0300 Subject: [PATCH 09/12] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=B0=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC=20=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BD=D1=8B=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/itmo/Graph.java | 19 +++++------------ tmp/results.txt | 34 +++++++++++++++---------------- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index c9ffe34..485d039 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -42,19 +42,13 @@ void parallelBFS(int startVertex) { visited[startVertex].set(true); nextVertexes.add(startVertex); - Boolean hasVertextsToProcess = true; - - while (hasVertextsToProcess) { + while (!nextVertexes.isEmpty()) { while (!nextVertexes.isEmpty()) { balancer.add(nextVertexes.poll()); } - hasVertextsToProcess = balancer.getQueues().stream() + balancer.getQueues().stream() .map((queue) -> executor.submit(() -> { - if (queue.isEmpty()) { - return false; - } - while (!queue.isEmpty()) { Integer vertex = queue.poll(); @@ -65,16 +59,13 @@ void parallelBFS(int startVertex) { } } } - - return true; - })).map((future) -> { + })).forEach((future) -> { try { - return future.get(); + future.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); - return false; } - }).reduce(hasVertextsToProcess, (acc, futureResult) -> acc && futureResult); + }); } } diff --git a/tmp/results.txt b/tmp/results.txt index 0d0bfaf..0109e02 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,36 +1,36 @@ Times for 10 vertices and 50 connections: Serial: 0 -Parallel: 3 +Parallel: 6 -------- Times for 100 vertices and 500 connections: -Serial: 0 -Parallel: 1 +Serial: 1 +Parallel: 4 -------- Times for 1000 vertices and 5000 connections: -Serial: 0 -Parallel: 2 +Serial: 1 +Parallel: 6 -------- Times for 10000 vertices and 50000 connections: -Serial: 3 -Parallel: 1 +Serial: 4 +Parallel: 9 -------- Times for 10000 vertices and 100000 connections: -Serial: 1 -Parallel: 2 +Serial: 2 +Parallel: 9 -------- Times for 50000 vertices and 1000000 connections: -Serial: 17 -Parallel: 4 +Serial: 20 +Parallel: 31 -------- Times for 100000 vertices and 1000000 connections: -Serial: 12 -Parallel: 2 +Serial: 19 +Parallel: 37 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 625 -Parallel: 285 +Serial: 629 +Parallel: 536 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 1019 -Parallel: 301 +Serial: 1112 +Parallel: 2922 -------- From 10ceeae5f8e4852663405927224f58d98aca7605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=94=D0=B0=D0=B2?= =?UTF-8?q?=D1=8B=D0=B4=D0=BE=D0=B2?= Date: Tue, 7 Oct 2025 15:55:21 +0300 Subject: [PATCH 10/12] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20CuncurrentQueueBalancer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/itmo/CuncurrentQueueBalancer.java | 27 +++++++++++ src/main/java/org/itmo/Graph.java | 47 ++++++++++--------- src/main/java/org/itmo/QueueBalancer.java | 26 ---------- tmp/results.txt | 34 +++++++------- 4 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 src/main/java/org/itmo/CuncurrentQueueBalancer.java delete mode 100644 src/main/java/org/itmo/QueueBalancer.java diff --git a/src/main/java/org/itmo/CuncurrentQueueBalancer.java b/src/main/java/org/itmo/CuncurrentQueueBalancer.java new file mode 100644 index 0000000..e0a7710 --- /dev/null +++ b/src/main/java/org/itmo/CuncurrentQueueBalancer.java @@ -0,0 +1,27 @@ +package org.itmo; + +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class CuncurrentQueueBalancer { + private AtomicInteger nextQueue; + private final List> queues; + + CuncurrentQueueBalancer(Integer size) { + nextQueue = new AtomicInteger(0); + queues = Stream.>generate(ConcurrentLinkedQueue::new).limit(size).collect(Collectors.toList()); + } + + void add(T value) { + Integer nextQueueIdx = nextQueue.getAndUpdate((val) -> (val + 1) % queues.size()); + queues.get(nextQueueIdx).add(value); + } + + List> getQueues() { + return queues; + } +} diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index 485d039..f0a8c43 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -1,15 +1,15 @@ package org.itmo; import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collector; import java.util.stream.Collectors; class Graph { + private final Integer CORES = 12; private final int V; private final ArrayList[] adjList; private final ExecutorService executor; @@ -21,7 +21,7 @@ class Graph { adjList[i] = new ArrayList<>(); } - executor = Executors.newFixedThreadPool(12); + executor = Executors.newFixedThreadPool(CORES); } void addEdge(int src, int dest) { @@ -35,19 +35,16 @@ void parallelBFS(int startVertex) { for (Integer i = 0; i < V; i++) { visited[i] = new AtomicBoolean(false); } - - QueueBalancer balancer = new QueueBalancer<>(12); - Queue nextVertexes = new ConcurrentLinkedQueue<>(); - visited[startVertex].set(true); - nextVertexes.add(startVertex); - while (!nextVertexes.isEmpty()) { - while (!nextVertexes.isEmpty()) { - balancer.add(nextVertexes.poll()); - } + CuncurrentQueueBalancer balancer = new CuncurrentQueueBalancer<>(CORES); + balancer.add(startVertex); - balancer.getQueues().stream() + while (true) { + CuncurrentQueueBalancer nextBalancer = new CuncurrentQueueBalancer<>(CORES); + + List> futures = balancer.getQueues().stream() + .filter((queue) -> !queue.isEmpty()) .map((queue) -> executor.submit(() -> { while (!queue.isEmpty()) { Integer vertex = queue.poll(); @@ -55,17 +52,25 @@ void parallelBFS(int startVertex) { for (int n : adjList[vertex]) { Boolean isVisited = visited[n].getAndSet(true); if (!isVisited) { - nextVertexes.add(n); + nextBalancer.add(n); } } } - })).forEach((future) -> { - try { - future.get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - }); + })).collect(Collectors.toList()); + + if (futures.isEmpty()) { + break; + } + + for (Future f : futures) { + try { + f.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + balancer = nextBalancer; } } diff --git a/src/main/java/org/itmo/QueueBalancer.java b/src/main/java/org/itmo/QueueBalancer.java deleted file mode 100644 index c961549..0000000 --- a/src/main/java/org/itmo/QueueBalancer.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.itmo; - -import java.util.ArrayDeque; -import java.util.List; -import java.util.Queue; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -class QueueBalancer { - private Integer nextQueue; - private final List> queues; - - QueueBalancer(Integer size) { - nextQueue = 0; - queues = Stream.>generate(ArrayDeque::new).limit(size).collect(Collectors.toList()); - } - - void add(T value) { - nextQueue = (nextQueue + 1) % queues.size(); - queues.get(nextQueue).add(value); - } - - List> getQueues() { - return queues; - } -} diff --git a/tmp/results.txt b/tmp/results.txt index 0109e02..c864868 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,36 +1,36 @@ Times for 10 vertices and 50 connections: Serial: 0 -Parallel: 6 +Parallel: 3 -------- Times for 100 vertices and 500 connections: -Serial: 1 -Parallel: 4 +Serial: 0 +Parallel: 2 -------- Times for 1000 vertices and 5000 connections: -Serial: 1 -Parallel: 6 +Serial: 0 +Parallel: 3 -------- Times for 10000 vertices and 50000 connections: -Serial: 4 -Parallel: 9 +Serial: 3 +Parallel: 13 -------- Times for 10000 vertices and 100000 connections: -Serial: 2 -Parallel: 9 +Serial: 1 +Parallel: 17 -------- Times for 50000 vertices and 1000000 connections: -Serial: 20 -Parallel: 31 +Serial: 17 +Parallel: 22 -------- Times for 100000 vertices and 1000000 connections: -Serial: 19 -Parallel: 37 +Serial: 15 +Parallel: 39 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 629 -Parallel: 536 +Serial: 651 +Parallel: 378 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 1112 -Parallel: 2922 +Serial: 1025 +Parallel: 3005 -------- From 3eb0b768a78427a6bfd24c493e9578611e1d2015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=94=D0=B0=D0=B2?= =?UTF-8?q?=D1=8B=D0=B4=D0=BE=D0=B2?= Date: Tue, 7 Oct 2025 16:46:23 +0300 Subject: [PATCH 11/12] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BB=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=BC=D1=8F=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 7 ++++++ ...ncer.java => ConcurrentQueueBalancer.java} | 14 +++++++----- src/main/java/org/itmo/Graph.java | 6 ++--- tmp/results.txt | 22 +++++++++---------- 4 files changed, 29 insertions(+), 20 deletions(-) rename src/main/java/org/itmo/{CuncurrentQueueBalancer.java => ConcurrentQueueBalancer.java} (57%) diff --git a/build.gradle.kts b/build.gradle.kts index 5370e10..bb005c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,3 +44,10 @@ tasks.register("jcstress") { } } +tasks.named("test") { + useJUnitPlatform() + + minHeapSize = "512m" + maxHeapSize = "8000m" +} + diff --git a/src/main/java/org/itmo/CuncurrentQueueBalancer.java b/src/main/java/org/itmo/ConcurrentQueueBalancer.java similarity index 57% rename from src/main/java/org/itmo/CuncurrentQueueBalancer.java rename to src/main/java/org/itmo/ConcurrentQueueBalancer.java index e0a7710..4c70f00 100644 --- a/src/main/java/org/itmo/CuncurrentQueueBalancer.java +++ b/src/main/java/org/itmo/ConcurrentQueueBalancer.java @@ -1,5 +1,6 @@ package org.itmo; +import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -7,21 +8,22 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -class CuncurrentQueueBalancer { +class ConcurrentQueueBalancer { private AtomicInteger nextQueue; - private final List> queues; + private final List> queues; - CuncurrentQueueBalancer(Integer size) { + ConcurrentQueueBalancer(int size) { nextQueue = new AtomicInteger(0); - queues = Stream.>generate(ConcurrentLinkedQueue::new).limit(size).collect(Collectors.toList()); + queues = Stream.>generate(ConcurrentLinkedQueue::new).limit(size) + .collect(Collectors.toList()); } - void add(T value) { + void add(Integer value) { Integer nextQueueIdx = nextQueue.getAndUpdate((val) -> (val + 1) % queues.size()); queues.get(nextQueueIdx).add(value); } - List> getQueues() { + List> getQueues() { return queues; } } diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index f0a8c43..fa1f569 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -9,7 +9,7 @@ import java.util.stream.Collectors; class Graph { - private final Integer CORES = 12; + private final Integer CORES = Runtime.getRuntime().availableProcessors() * 2; private final int V; private final ArrayList[] adjList; private final ExecutorService executor; @@ -37,11 +37,11 @@ void parallelBFS(int startVertex) { } visited[startVertex].set(true); - CuncurrentQueueBalancer balancer = new CuncurrentQueueBalancer<>(CORES); + ConcurrentQueueBalancer balancer = new ConcurrentQueueBalancer(CORES); balancer.add(startVertex); while (true) { - CuncurrentQueueBalancer nextBalancer = new CuncurrentQueueBalancer<>(CORES); + ConcurrentQueueBalancer nextBalancer = new ConcurrentQueueBalancer(CORES); List> futures = balancer.getQueues().stream() .filter((queue) -> !queue.isEmpty()) diff --git a/tmp/results.txt b/tmp/results.txt index c864868..c59da6f 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,36 +1,36 @@ Times for 10 vertices and 50 connections: Serial: 0 -Parallel: 3 +Parallel: 4 -------- Times for 100 vertices and 500 connections: Serial: 0 -Parallel: 2 +Parallel: 6 -------- Times for 1000 vertices and 5000 connections: Serial: 0 -Parallel: 3 +Parallel: 4 -------- Times for 10000 vertices and 50000 connections: Serial: 3 -Parallel: 13 +Parallel: 12 -------- Times for 10000 vertices and 100000 connections: Serial: 1 Parallel: 17 -------- Times for 50000 vertices and 1000000 connections: -Serial: 17 -Parallel: 22 +Serial: 15 +Parallel: 21 -------- Times for 100000 vertices and 1000000 connections: -Serial: 15 +Serial: 12 Parallel: 39 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 651 -Parallel: 378 +Serial: 252 +Parallel: 418 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 1025 -Parallel: 3005 +Serial: 1613 +Parallel: 586 -------- From 6d7ff2aa7e312884b247101c9a410e19676ef026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=94=D0=B0=D0=B2?= =?UTF-8?q?=D1=8B=D0=B4=D0=BE=D0=B2?= Date: Tue, 7 Oct 2025 17:11:25 +0300 Subject: [PATCH 12/12] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D0=B8=D1=80?= =?UTF-8?q?=D1=83=D0=B5=D0=BC=20=D1=80=D0=B5=D0=B7=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jcstress-results-2025-10-07-17-07-38.bin.gz | Bin 0 -> 10 bytes jcstress-results-2025-10-07-17-08-30.bin.gz | Bin 0 -> 10 bytes jcstress-results-2025-10-07-17-08-55.bin.gz | Bin 0 -> 10 bytes jcstress-results-2025-10-07-17-09-34.bin.gz | Bin 0 -> 10 bytes jcstress-results-2025-10-07-17-10-17.bin.gz | Bin 0 -> 2472 bytes results/index.html | 124 ++++ results/org.itmo.JCBFSStressTest.html | 577 ++++++++++++++++++ .../org/itmo/ConcurrentQueueBalancer.java | 1 - src/main/java/org/itmo/Graph.java | 4 + src/main/java/org/itmo/UnsafeCounter.java | 13 - src/test/java/org/itmo/JCBFSStressTest.java | 85 +++ src/test/java/org/itmo/UnsafeCounterTest.java | 27 - 12 files changed, 790 insertions(+), 41 deletions(-) create mode 100644 jcstress-results-2025-10-07-17-07-38.bin.gz create mode 100644 jcstress-results-2025-10-07-17-08-30.bin.gz create mode 100644 jcstress-results-2025-10-07-17-08-55.bin.gz create mode 100644 jcstress-results-2025-10-07-17-09-34.bin.gz create mode 100644 jcstress-results-2025-10-07-17-10-17.bin.gz create mode 100644 results/index.html create mode 100644 results/org.itmo.JCBFSStressTest.html delete mode 100644 src/main/java/org/itmo/UnsafeCounter.java create mode 100644 src/test/java/org/itmo/JCBFSStressTest.java delete mode 100644 src/test/java/org/itmo/UnsafeCounterTest.java diff --git a/jcstress-results-2025-10-07-17-07-38.bin.gz b/jcstress-results-2025-10-07-17-07-38.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..5105e8bffba55252e59dd361d3906d03eb845364 GIT binary patch literal 10 Ncmb2|=3oGW{{RPK0kQx9 literal 0 HcmV?d00001 diff --git a/jcstress-results-2025-10-07-17-08-30.bin.gz b/jcstress-results-2025-10-07-17-08-30.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..5105e8bffba55252e59dd361d3906d03eb845364 GIT binary patch literal 10 Ncmb2|=3oGW{{RPK0kQx9 literal 0 HcmV?d00001 diff --git a/jcstress-results-2025-10-07-17-08-55.bin.gz b/jcstress-results-2025-10-07-17-08-55.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..5105e8bffba55252e59dd361d3906d03eb845364 GIT binary patch literal 10 Ncmb2|=3oGW{{RPK0kQx9 literal 0 HcmV?d00001 diff --git a/jcstress-results-2025-10-07-17-09-34.bin.gz b/jcstress-results-2025-10-07-17-09-34.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..5105e8bffba55252e59dd361d3906d03eb845364 GIT binary patch literal 10 Ncmb2|=3oGW{{RPK0kQx9 literal 0 HcmV?d00001 diff --git a/jcstress-results-2025-10-07-17-10-17.bin.gz b/jcstress-results-2025-10-07-17-10-17.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..0172ab79f5fc877a7de5065ac950577decb77964 GIT binary patch literal 2472 zcmV;Z30L+XiwFP!00000|Lt8(Y#YZF9!b=XWyO~DXV*bmI!^4Qfhg`DcUeQIX!^DLy;hd1Z`2YJrw=9 zw?Tmdy%gvzowq+UC6bb|T*C|NJz$5svomjI-@NzD+j+aoAOD;5@7Wefn$}jrtZK$i z>3(9TXj4nG?SyV@T56(bmdjd^nwFhd(`>q`*|jo_fBl~y%wPV}cY4WSo(vRCV^iOv zWG2t}%y@ied_FS{pBbxW7@B3z0F$g!;aZ;bX~r%kSKHUCQN27fXYA^hX;d_WvhqU} zc0%1^EXZhnN8MH3LV4YWvja9&DV)1}2*a#dGpJ_y#cQ35yZtUWg;??a-O8M0eT6(A zea^vhjXDSQDwE*!ArkbiJn`_#e{+L;`M=+s{d+GN&5_eZvr^T|+M-#~a%5oBwC?9h zInuAQUfMZwrlQv8O_NqF-Jpv%Sb4@=FKNzoU1$(Sp{vTAIx>tqeUm<$xFwMDf`NxZ#SOnWA~a)*^*WyiNP zc4C#> zH}a-gEzrF(>pXuPZ7Vd_xmK?dLi&kI@OzzYFA&lL$GwE~eZ+=x9AuIJT}fmtOWgzI zs(CoC< zl}YE>j*?yS%3RxEBHgp8R%vF!8g!Lt&CHsXb}$brdwFO5yj4vtvyMC2^=i$6J}&<1 z-j&^d{rrbasIH_w_NWHMrd)A5)bqe1@lNva`|6b?V~m|e&Nw3kTAP?NYL(`bOl=2O zGTE0ix8@oxk;dML-{!~1q?Vc_aLr@4Ny(*7s&m(ujWbqHF|IL317nm-PT$;QAd=9G zqFG{AGka%kep;dA-1NM`-ZX zP9t`}Zr|DbgZ|)0=U?w7{W;G#>}Z zZPngp`Tc``d++_Jdw=XBz4K(aY^tSsXK-@l6qvQWZI(;*>gTUJeI0pih^3=!J59-H zhu5xVluV2DeXdy6tF{);l*}sCYZXc^ItA>iR@66j22#3du;P}@ei?l63?$FDDPcGh z(q|UfnfOXsrED6k#4{_oc%iu%B_m$*9=`#eOC%Fa&(FH~m4~NB+*2>5r}JwC1`BMg zRjato_Eh*yi4A5Iuk{PdOyCPQUyi55=^HwY7c`4;i@&l+$*0<0lq-X=WlJrVwK&7e zs%d%sgyvkXLyKxLzFdf}QxCYDPIeUEFsskhat)Z?*Vj{U6mx)1Kx$w{Wkzl=ZbEfyvR zkxL#?ruv|h?z^Dty6b+&noxFNX?b-qlW(=9wi(1p2Z`&a^pOtkA{06U$vLO|SnC|I z&)h1Lh@NiI7p=S zgSkw6_=2MXIq8Ts@dhFmXu=&55+(t&FMeWV0jDY~WEo)F;IWaV$=aQY$H#}G5GHt= z$3_-NwjkMtM2BRj4N!=Zl$Ir4ln^Ka)1-nx5dok8djYi!11KDK=18FM3wAQ%&gSmR zEl|y4wb><5TsQy}vM9)6DkboU6M<+Wcm5J2&!S-m zB{b|v81|6YmoN+)sHdZ0`vs0`Y>(sFtgt-*SxIq8L6C6qF*qSmL;@&$1IOni8bE;_ zKvy*NA2jTU7&b;9_ZfDG9stjYl8{nx4WJ8}co%^p0zd(4W?(}YRR{qn4nC$JrDRE# z1U`j05t#5v?a1H+5C#<*IDvNxUD5dqXxI@jZ2xWng8<}FJb$DlC3v<#Ko1}=;aXuN zfWjvXDgdDe&^=APfQB6b!-g%awZbPP2oPqpP)v!UEX!&100PtGPZ20002HuP7Sk9@I8bE|Az@GfDC8vt zndcQzPAmBFgW!ZqkCDI$zz2*`goG2VA3qRNqRfj5t~~~)iQ5Pi5dn&@9%sTB#Q~rY zd0rGHLBd#OaKacxBya*&;KEv=z!*i#M^aK8$0?GCuSf?c{61qOfTGXq3od06{76bD zgiDW+Fl?9r!@5&=LV}OMJ%IBE-+Yu(X;Bbmoc{yU#777d5r7GR2aHgJ1QRU_3QAH; z@(PbQ5uET@rpVv~AsC?u1t(e-6q2GWN`k=SAHxJE{4`S}fWnU~V1(jP0ENsY1wJiF z_-Ur#gr8iA1W@=dU1Nx%0Thtn%41-f`Vb8}0)`EG9oEB4Pe@21yd?!rl#-l;p~r6M zBL0y}6mTNUuQQ+c2t~`c8AVBvI6=ghD1sB>L?mz`%o_zD3{f + +Java Concurrency Stress test report + + + + + + + + +
+

+100% +

+ + + +
 
Overall pass rate: 1/1 
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
java.specification.nameJava Platform API Specification
java.specification.vendorOracle Corporation
java.specification.version21
java.vendorEclipse Adoptium
java.version21.0.8
java.vm.nameOpenJDK 64-Bit Server VM
java.vm.vendorEclipse Adoptium
java.vm.version21.0.8+9-LTS
os.archaarch64
os.nameMac OS X
os.version15.6
+
+
+

FAILED tests

+

Strong asserts were violated. Correct implementations should have no assert failures here.

+ +
+None! +
+
+
+

ERROR tests

+

Tests break for some reason, other than failing the assert. Correct implementations should have none.

+ +
+None! +
+
+
+

INTERESTING tests

+

Some interesting behaviors observed. This is for the plain curiosity.

+ +
+None! +
+
+
+

All tests

+

+ + + + + + + +
   org.itmo.JCBFSStressTest107PASSED
+
+ + diff --git a/results/org.itmo.JCBFSStressTest.html b/results/org.itmo.JCBFSStressTest.html new file mode 100644 index 0000000..4d6d7eb --- /dev/null +++ b/results/org.itmo.JCBFSStressTest.html @@ -0,0 +1,577 @@ + + + +Java Concurrency Stress test report + + + +

org.itmo.JCBFSStressTest

+

Description and references

+

null

+

Environment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
java.specification.nameJava Platform API Specification
java.specification.vendorOracle Corporation
java.specification.version21
java.vendorEclipse Adoptium
java.version21.0.8
java.vm.nameOpenJDK 64-Bit Server VM
java.vm.vendorEclipse Adoptium
java.vm.version21.0.8+9-LTS
os.archaarch64
os.nameMac OS X
os.version15.6
+

Results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Compilation ModeScheduling ClassJava OptionsStatusObserved States
10
Acceptable
Все вершины были обойдены
split
+    actor1: Interpreter
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1452051
split
+    actor1: C1
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1288211
split
+    actor1: C2
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1503251
split
+    actor1: C2
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1127158550]
+
OK1308691
split
+    actor1: C2
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1214536811]
+
OK1359891
split
+    actor1: C2
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1710329551]
+
OK1431571
split
+    actor1: C2
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1922078931]
+
OK1349651
split
+    actor1: C2
+    actor2: Interpreter
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=545851348]
+
OK1728531
split
+    actor1: Interpreter
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1462291
split
+    actor1: C1
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1462291
split
+    actor1: C2
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1431571
split
+    actor1: C2
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1047453325]
+
OK1503251
split
+    actor1: C2
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1714780508]
+
OK1462291
split
+    actor1: C2
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=2046472483]
+
OK1329171
split
+    actor1: C2
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=422445359]
+
OK1380371
split
+    actor1: C2
+    actor2: C1
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=480402827]
+
OK1411091
split
+    actor1: Interpreter
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1513491
split
+    actor1: Interpreter
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1764780768]
+
OK1411091
split
+    actor1: Interpreter
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1861118542]
+
OK1318931
split
+    actor1: Interpreter
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=2020796978]
+
OK1400851
split
+    actor1: Interpreter
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=567575326]
+
OK1431571
split
+    actor1: Interpreter
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=743746632]
+
OK1318931
split
+    actor1: C1
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1493011
split
+    actor1: C1
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1180520203]
+
OK1462291
split
+    actor1: C1
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1746447779]
+
OK1421331
split
+    actor1: C1
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1884818911]
+
OK1462291
split
+    actor1: C1
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=437442740]
+
OK1800211
split
+    actor1: C1
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=722847980]
+
OK1421331
split
+    actor1: C2
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant]
+
OK1923091
split
+    actor1: C2
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=145015542]
+
OK1728531
split
+    actor1: C2
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1455975245]
+
OK1390611
split
+    actor1: C2
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=1786103352]
+
OK1462291
split
+    actor1: C2
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=329137933]
+
OK1380371
split
+    actor1: C2
+    actor2: C2
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-Dfile.encoding=UTF-8, -Duser.country=RU, -Duser.language=ru, -Duser.variant, -XX:+StressLCM, -XX:+StressGCM, -XX:+StressIGVN, -XX:+StressCCP, -XX:StressSeed=55694347]
+
OK1370131
+

Messages

+

VM Output Streams

+

VM Error Streams

+ + diff --git a/src/main/java/org/itmo/ConcurrentQueueBalancer.java b/src/main/java/org/itmo/ConcurrentQueueBalancer.java index 4c70f00..0b517df 100644 --- a/src/main/java/org/itmo/ConcurrentQueueBalancer.java +++ b/src/main/java/org/itmo/ConcurrentQueueBalancer.java @@ -1,6 +1,5 @@ package org.itmo; -import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index fa1f569..b3f6a20 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -24,6 +24,10 @@ class Graph { executor = Executors.newFixedThreadPool(CORES); } + List[] getAdjList() { + return adjList; + } + void addEdge(int src, int dest) { if (!adjList[src].contains(dest)) { adjList[src].add(dest); diff --git a/src/main/java/org/itmo/UnsafeCounter.java b/src/main/java/org/itmo/UnsafeCounter.java deleted file mode 100644 index 1041a21..0000000 --- a/src/main/java/org/itmo/UnsafeCounter.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.itmo; - -public class UnsafeCounter { - private int counter = 0; - - public void increment() { - counter++; // <-- гонка данных - } - - public int get() { - return counter; - } -} diff --git a/src/test/java/org/itmo/JCBFSStressTest.java b/src/test/java/org/itmo/JCBFSStressTest.java new file mode 100644 index 0000000..14a4812 --- /dev/null +++ b/src/test/java/org/itmo/JCBFSStressTest.java @@ -0,0 +1,85 @@ +package org.itmo; + +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; + +import org.openjdk.jcstress.annotations.Actor; +import org.openjdk.jcstress.annotations.Arbiter; +import org.openjdk.jcstress.annotations.Expect; +import org.openjdk.jcstress.annotations.JCStressTest; +import org.openjdk.jcstress.annotations.Outcome; +import org.openjdk.jcstress.annotations.State; +import org.openjdk.jcstress.infra.results.L_Result; + +@JCStressTest +@Outcome(id = "10", expect = Expect.ACCEPTABLE, desc = "Все вершины были обойдены") +@Outcome(expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть вершин не была обойдена") +@State +public class JCBFSStressTest { + private static final int CORES_NUM = 12; + private static final int VERTICES_NUM = 10; + + Graph graph = new Graph(VERTICES_NUM); + AtomicBoolean[] visited = new AtomicBoolean[VERTICES_NUM]; + ConcurrentQueueBalancer queueBalancer = new ConcurrentQueueBalancer(CORES_NUM); + ConcurrentQueueBalancer nextBalancer = new ConcurrentQueueBalancer(CORES_NUM); + + public JCBFSStressTest() { + graph.addEdge(0, 1); + graph.addEdge(0, 2); + graph.addEdge(0, 3); + graph.addEdge(0, 4); + + graph.addEdge(1, 5); + graph.addEdge(3, 6); + graph.addEdge(2, 7); + graph.addEdge(4, 8); + graph.addEdge(4, 9); + + for (int i = 0; i < VERTICES_NUM; ++i) { + visited[i] = new AtomicBoolean(false); + } + + for (int i = 0; i < 5; ++i) { + visited[i].set(true); + } + } + + @Actor + void actor1() { + Queue q = new ConcurrentLinkedQueue<>(); + q.add(1); + q.add(3); + step(q); + } + + @Actor + void actor2() { + Queue q = new ConcurrentLinkedQueue<>(); + q.add(2); + q.add(4); + step(q); + } + + void step(Queue vertecies) { + List[] adjList = graph.getAdjList(); + while (!vertecies.isEmpty()) { + Integer vertex = vertecies.poll(); + + for (int n : adjList[vertex]) { + Boolean isVisited = visited[n].getAndSet(true); + if (!isVisited) { + nextBalancer.add(n); + } + } + } + } + + @Arbiter + public void arbiter(L_Result r) { + r.r1 = Stream.of(visited).filter(AtomicBoolean::get).count(); + } +} diff --git a/src/test/java/org/itmo/UnsafeCounterTest.java b/src/test/java/org/itmo/UnsafeCounterTest.java deleted file mode 100644 index a831605..0000000 --- a/src/test/java/org/itmo/UnsafeCounterTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.itmo; - -import org.openjdk.jcstress.annotations.*; -import org.openjdk.jcstress.infra.results.I_Result; - -@JCStressTest -@Outcome(id = "5", expect = Expect.ACCEPTABLE, desc = "Все 5 инкрементов выполнены корректно") -@Outcome(id = "1", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@Outcome(id = "2", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@Outcome(id = "3", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@Outcome(id = "4", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@State -public class UnsafeCounterTest { - - private UnsafeCounter counter = new UnsafeCounter(); - - @Actor public void actor1() { counter.increment(); } - @Actor public void actor2() { counter.increment(); } - @Actor public void actor3() { counter.increment(); } - @Actor public void actor4() { counter.increment(); } - @Actor public void actor5() { counter.increment(); } - - @Arbiter - public void arbiter(I_Result r) { - r.r1 = counter.get(); - } -}