-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
21
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
StructuredTaskScope.ShutdownOnFailure::joinUntil breaks app execution for big amounts of tasks.
Its duration rise without obvious formula, then it fails with about 30_000_000 tasks.
It doesn't respect chosen deadline. It takes 100% of CP and in most cases brings memory exception.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Duration should rise GRADUALLY with bigger amounts of tasks.
joinUntil should stop after the deadline.
---------- BEGIN SOURCE ----------
import java.time.Instant;
import java.time.Duration;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
public class TestJoinUntil {
static final Scanner scanner = new Scanner(System.in);
static final AtomicLong counter = new AtomicLong(0);
static final String RESUME_STRING = "0";
static final List<Integer> STEPS = List.of(
1,
10,
100,
1_000,
10_000,
100_000,
1_000_000,
10_000_000,
20_000_000,
30_000_000,
31_000_000,
32_000_000,
33_000_000,
34_000_000,
35_000_000,
36_000_000,
37_000_000,
38_000_000,
39_000_000,
40_000_000,
50_000_000,
60_000_000,
70_000_000
);
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
Duration duration;
for (int currentConcurrency : STEPS) {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
for (int i = 0; i < currentConcurrency; i++) {
scope.fork(TestJoinUntil::incCount);
}
Instant startTime = Instant.now();
scope.joinUntil(startTime.plusSeconds(10));
scope.throwIfFailed();
Instant endTime = Instant.now();
duration = Duration.between(startTime, endTime);
}
long counterValue = counter.get();
System.out.printf("%d.%06d seconds. Concurrency=%d.%s Enter %s to resume: ",
duration.getSeconds(),
duration.getNano() / 1_000,
currentConcurrency,
(counterValue == currentConcurrency) ? "" : "Counter=" + counterValue + " (" + (currentConcurrency - counterValue) + " tasks were failed). ",
RESUME_STRING);
if (! scanner.nextLine().equals(RESUME_STRING)) {
break;
}
counter.set(0);
}
}
public static long incCount() {
return counter.incrementAndGet();
}
}
---------- END SOURCE ----------
FREQUENCY : always
StructuredTaskScope.ShutdownOnFailure::joinUntil breaks app execution for big amounts of tasks.
Its duration rise without obvious formula, then it fails with about 30_000_000 tasks.
It doesn't respect chosen deadline. It takes 100% of CP and in most cases brings memory exception.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Duration should rise GRADUALLY with bigger amounts of tasks.
joinUntil should stop after the deadline.
---------- BEGIN SOURCE ----------
import java.time.Instant;
import java.time.Duration;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
public class TestJoinUntil {
static final Scanner scanner = new Scanner(System.in);
static final AtomicLong counter = new AtomicLong(0);
static final String RESUME_STRING = "0";
static final List<Integer> STEPS = List.of(
1,
10,
100,
1_000,
10_000,
100_000,
1_000_000,
10_000_000,
20_000_000,
30_000_000,
31_000_000,
32_000_000,
33_000_000,
34_000_000,
35_000_000,
36_000_000,
37_000_000,
38_000_000,
39_000_000,
40_000_000,
50_000_000,
60_000_000,
70_000_000
);
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
Duration duration;
for (int currentConcurrency : STEPS) {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
for (int i = 0; i < currentConcurrency; i++) {
scope.fork(TestJoinUntil::incCount);
}
Instant startTime = Instant.now();
scope.joinUntil(startTime.plusSeconds(10));
scope.throwIfFailed();
Instant endTime = Instant.now();
duration = Duration.between(startTime, endTime);
}
long counterValue = counter.get();
System.out.printf("%d.%06d seconds. Concurrency=%d.%s Enter %s to resume: ",
duration.getSeconds(),
duration.getNano() / 1_000,
currentConcurrency,
(counterValue == currentConcurrency) ? "" : "Counter=" + counterValue + " (" + (currentConcurrency - counterValue) + " tasks were failed). ",
RESUME_STRING);
if (! scanner.nextLine().equals(RESUME_STRING)) {
break;
}
counter.set(0);
}
}
public static long incCount() {
return counter.incrementAndGet();
}
}
---------- END SOURCE ----------
FREQUENCY : always