Benchmarking study accompanying the paper "Assessing the Efficiency of Virtual Threads in Java for a Parallel Particle Swarm Optimization Implementation" (M. S. Korelov, M. A. Khromeeva).
The experiment compares wall-clock execution time of two parallel PSO schemes across three Java executor types and two fitness-evaluation regimes.
| Dimension | Values |
|---|---|
| Algorithm | PSPSO_SYNC_BARRIER, PAPSO_ASYNC_NO_BARRIER |
| Regime | PURE_CPU, MIXED_BLOCKING |
| Executor | FIXED_POOL, WORK_STEALING, VIRTUAL_PER_TASK |
PSPSO uses a per-iteration CountDownLatch barrier: all particles are
evaluated in parallel, then velocities and positions are updated
sequentially.
PAPSO assigns each particle an independent task chain of ITERATIONS
tasks with no global barrier. Particles proceed asynchronously; the global
best is updated whenever any task completes.
PURE_CPU — constant CPU workload only (2 000 trigonometric iterations).
MIXED_BLOCKING — CPU workload plus a random sleep drawn from a bounded
exponential distribution (mean 2 ms, max 10 ms), realised via
Thread.sleep. This models I/O-bound-like blocking inside the fitness call.
- JDK 21+ (virtual threads are required; tested on JDK 25.0.2)
- No external dependencies
VirtualThreadsPSO/
├── README.md
├── out/ ← compiled classes (git-ignored)
└── src/
├── RunCaseStudy.java ← entry point
├── config/
│ └── BenchConfig.java ← all tuneable constants
├── core/
│ ├── Algorithm.java
│ ├── Regime.java
│ ├── ExecutorKind.java
│ ├── Particle.java
│ └── GlobalBest.java
├── runner/
│ ├── CellRunner.java
│ └── SingleRunRunner.java
├── algorithm/
│ ├── PSPSORunner.java
│ └── PAPSORunner.java
├── fitness/
│ └── FitnessEvaluator.java
├── stats/
│ ├── Stats.java
│ ├── RunResult.java
│ ├── CellStats.java
│ └── StatsUtils.java
└── output/
└── TablePrinter.java
# Compile (from project root)
mkdir -p out
find src -name "*.java" | xargs javac -d out
# Run
java -cp out RunCaseStudyAll parameters are in src/config/BenchConfig.java:
| Constant | Default | Meaning |
|---|---|---|
DIM |
30 | Search space dimensionality |
SWARM_SIZE |
1000 | Number of particles |
ITERATIONS |
50 | PSO iterations per run |
WARMUP_RUNS |
5 | Discarded warm-up runs |
MEASURED_RUNS |
30 | Measured runs per cell |
BASE_SEED |
123456789 | Root seed for all RNGs |
W |
0.7 | Inertia weight |
C1, C2 |
1.4 | Cognitive / social coefficients |
X_MIN, X_MAX |
−5.12, 5.12 | Search domain bounds |
CPU_WORK |
2 000 | Synthetic CPU loop length |
BLOCKING_MEAN_MS |
2 | Mean blocking delay (ms) |
BLOCKING_MAX_MS |
10 | Maximum blocking delay (ms) |
- Each run is seeded from
BASE_SEEDwith disjoint offsets for warm-up and measured runs:- warm-up run
w→ seedBASE_SEED + w - measured run
r→ seedBASE_SEED + 10_000 + r
- warm-up run
- Every particle owns a private
SplittableRandominstance; there is no shared RNG state between particles. - PSPSO trajectories are fully deterministic for a fixed seed regardless of executor type.
- PAPSO trajectories depend on task scheduling order and may differ between executor types; this is expected and discussed in the paper.
Progress lines with timestamps are printed to stdout during execution.
After all cells complete, two table pairs are printed (one per regime):
- Time table — mean / std / min / max of wall-clock duration (ms). Primary performance metric.
- Best-value table — mean / std / min / max of the global best fitness value. Reported as an optimisation-trajectory sanity indicator only; not used to compare executor performance.
- OS: Ubuntu 24.04.3 LTS
- CPU: AMD Ryzen 7 8745HS (8 cores)
- RAM: 32 GB
- JDK: 25.0.2