This wrapper facilitates the automated execution of the SPECjbb2005 benchmark. SPECjbb2005 is SPEC's benchmark for evaluating the performance of server-side Java. It emulates a three-tier client/server system with emphasis on the middle tier, exercising the JVM, JIT compiler, garbage collection, threads, and operating system aspects. It also benchmarks CPUs, caches, memory hierarchy, and SMP scalability. The 2005 version introduced XML processing and BigDecimal computations for more realistic workload representation.
The wrapper provides:
- Automated SPECjbb2005 configuration and execution.
- Automatic warehouse sizing based on system CPU count.
- Support for multiple JVM instances across NUMA nodes.
- Optional NUMA node pinning for memory and CPU binding.
- Configurable Java version selection (11, 17, 21, 23, 24, 25).
- Support for x86_64 and aarch64 architectures.
- Support for multiple OS variants (RHEL, Ubuntu, SLES, Amazon Linux).
- Result collection, processing, and verification.
- CSV and JSON output formats.
- System configuration metadata capture.
- Integration with test_tools framework.
- Optional Performance Co-Pilot (PCP) integration.
For more information see: https://www.spec.org/jbb2005/
SPECjbb Options:
--inc-warehouses <value>: How many warehouses to increment each time.
Default is end_warehouse/8 for systems with > 16 CPUs, else 2.
--java_exec <path>: Path to the Java executable to use.
Default is auto-detected based on OS and java_version.
--java_version <number>: Version of Java to run (11, 17, 21, 23, 24, 25).
Default is 21.
--max_jvms: Run one JVM per NUMA node (sets nr_jvms to number of NUMA nodes).
--node_pinning <y|n>: Bind JVMs to NUMA nodes using numactl. Default is n.
--nr-jvms <value>: Number of JVMs to use. Default is 1 and the number of NUMA nodes.
Accepts comma-separated list (e.g., "1,node" to run with 1 JVM then all nodes).
--regression: Regression mode with reduced settings (measurement=120s, 8 warehouse data points).
--runtime <seconds>: Seconds to run the test for.
--specjbb_kit <filename>: Name of the SPECjbb2005 kit archive in ~/uploads.
Default is the most recent SPECjbb2005_kit* file found in ~/uploads.
--start-warehouses <value>: Number of warehouses to start at.
Default is calculated based on CPU count; 2 if CPUs <= 16.
--stop-warehouses <value>: Number of warehouses to stop at. Default is 2x the number of CPUs.
--usage: Display this usage message.
General test_tools options:
--debug: Enable bash -x debug output for wrapper troubleshooting.
--home_parent <value>: Parent home directory. If not set, defaults to current working directory.
--host_config <value>: Host configuration name, defaults to current hostname.
--iterations <value>: Number of times to run the test, defaults to 1.
--json_skip: Skip JSON conversion of test CSV results.
--no_pkg_install: Do not install any packages (system or pip). Useful for pre-provisioned systems.
--no_system_packages: Do not install system packages via the package manager. Pip packages are still installed.
--no_pip_packages: Do not install Python pip packages. System packages are still installed.
--run_label <value>: Label to associate with the run. No default.
--run_user: User that is actually running the test on the test system. Defaults to current user.
--sys_type: Type of system working with (aws, azure, hostname). Defaults to hostname.
--sysname: Name of the system running, used in determining config files. Defaults to hostname.
--test_tools_release <tag>: Version tag of test_tools-wrappers to check out and use.
--tuned_setting: Used in naming the results directory. For RHEL, defaults to current active tuned profile.
For non-RHEL systems, defaults to 'none'. If set to a profile name, activates that tuned profile.
--use_pcp: Enable Performance Co-Pilot monitoring during test execution.
--verify_skip: Skip result verification against the Pydantic schema.
--tools_git <value>: Git repo to retrieve the required tools from.
Default: https://github.com/redhat-performance/test_tools-wrappers
--usage: Display this usage message.
The specjbb_run script performs the following workflow:
-
Environment Setup:
- Archives any previous SPECjbb results from
/tmpinto a timestamped archive directory. - Clones the test_tools-wrappers repository if not present (default: ~/test_tools).
- Sources error codes and general setup utilities.
- Gathers hardware information via
gather_data.
- Archives any previous SPECjbb results from
-
Package Installation:
- Installs required base dependencies via package_tool using
specjbb.json(bc, zip, unzip, numactl, git). - Installs Java packages for the selected version via the corresponding
specjbb_<version>.jsonfile. - Dependencies are defined for different OS variants (RHEL, Ubuntu, SLES, Amazon Linux).
- Installs required base dependencies via package_tool using
-
Java Detection:
- RHEL/CentOS/Amazon Linux: Uses
/etc/alternatives/jre_<version>/bin/java. - Ubuntu: Uses
/usr/lib/jvm/java-<version>-openjdk-*/bin/java.
- RHEL/CentOS/Amazon Linux: Uses
-
Warehouse Sizing:
- Automatically detects the number of CPUs in the system.
- Calculates ending warehouse count as 2x the number of logical CPUs.
- For systems with > 16 CPUs: calculates start and increment warehouses to produce ~8 data points.
- For systems with <= 16 CPUs: starts at 2 warehouses, incrementing by 2.
- In regression mode: uses 8 evenly-spaced warehouse data points with 120s measurement time.
-
SPECjbb Kit Extraction:
- Locates the SPECjbb2005 kit archive in
~/uploads(or uses--specjbb_kitpath). - Extracts the kit into the script's working directory.
- Locates the SPECjbb2005 kit archive in
-
JVM Configuration:
- Determines number of JVMs to run based on
--nr-jvmsor--max_jvmssettings. - Calculates Java heap size (
-Xms/-Xmx) based on CPU count and number of JVMs. - Scales stack size proportionally: base of 8192 MiB, increasing every 256 CPUs per JVM.
- Determines number of JVMs to run based on
-
Test Execution:
- Generates a
prop.filefromSPECjbb.propswith calculated warehouse and timing parameters. - For multi-JVM runs: starts a SPECjbb Controller process first, then launches individual JVM instances.
- Optionally binds each JVM to its corresponding NUMA node via
numactl --membind --cpunodebindwhen--node_pinning yis set. - Each JVM runs
spec.jbb.JBBmainwith the generated properties file. - Waits for all JVM processes to complete.
- Executes for the specified number of iterations.
- Generates a
-
Data Collection:
- Captures system configuration (CPU, memory, NUMA topology, kernel version) via the per-JVM
run.shhelper. - Records SPECjbb output files with warehouse counts and business operations per second (BOPs).
- Logs timestamps for each test run.
- Optionally records PCP performance data.
- Captures system configuration (CPU, memory, NUMA topology, kernel version) via the per-JVM
-
Result Processing:
- Extracts warehouse and BOPs data from SPECjbb output files.
- For multi-JVM runs: sums warehouse counts and BOPs across all JVMs.
- Sorts data by warehouse count and generates CSV with aggregated results.
- Creates JSON output for verification.
-
Verification:
- Validates results against the Pydantic schema (
results_schema.py). - Ensures all required fields are present and valid (Warehouses > 0, Bops > 0, Numb_JVMs > 0, timestamps).
- Uses
csv_to_jsonandverify_resultsfrom test_tools.
- Validates results against the Pydantic schema (
-
Output:
- Creates timestamped results directory in
/tmp/results_specjbb_<tuned>_<YYYY.MM.DD-HH.MM.SS>. - Saves raw SPECjbb output files, processed CSV/JSON, and system metadata.
- Optionally saves PCP performance data.
- Archives results to configured storage location via
save_results.
- Creates timestamped results directory in
Location of underlying workload: SPECjbb2005 is a licensed product. You must upload the kit yourself. Place the SPECjbb2005_kit* archive in ~/uploads. The wrapper will automatically locate and extract the most recent kit found in that directory.
General packages required: bc, zip, unzip, numactl, git
Java packages (installed automatically based on --java_version):
- Java 21 (default):
- RHEL: java-21-openjdk-headless
- Ubuntu: openjdk-21-jre-headless
- SLES: java-21-openjdk
- Amazon Linux: java-21-amazon-corretto
- Java 17:
- Ubuntu: openjdk-17-jre-headless
- SLES: java-17-openjdk
- Amazon Linux: java-17-amazon-corretto
- Java 11:
- Ubuntu: openjdk-11-jre-headless
- SLES: java-11-openjdk
- Amazon Linux: java-11-amazon-corretto
- Java 23: Amazon Linux only (java-23-amazon-corretto)
- Java 24: Amazon Linux only (java-24-amazon-corretto)
- Java 25: Ubuntu only (openjdk-25-jre-headless)
To run:
# Upload your SPECjbb2005 kit first
cp SPECjbb2005_kit*.tar.gz ~/uploads/
# Clone and run
git clone https://github.com/redhat-performance/specjbb-wrapper
cd specjbb-wrapper/specjbb
./specjbb_runThe script will automatically detect the system size and select appropriate warehouse parameters.
SPECjbb2005 (Java Business Benchmark) emulates a three-tier client/server system, focusing on the middle (business logic) tier. It models a wholesale company with warehouses and associated sales districts.
-
Warehouses: The primary scaling parameter. Each warehouse represents an independent unit of work. More warehouses means more concurrent threads and higher system utilization. The wrapper automatically scales warehouses based on CPU count.
-
JVM Instances: The number of independent Java Virtual Machine processes. Running one JVM per NUMA node can improve memory locality. The wrapper supports 1 to N JVMs, where N is the number of NUMA nodes.
-
Ramp-up Time: Warm-up period (in seconds) before measurement begins. Default is 60 seconds. Allows the JIT compiler to optimize hot paths.
-
Measurement Time: Duration (in seconds) of the actual measurement period. Default is 60 seconds; regression mode uses 120 seconds.
-
Performance Metric: SPECjbb2005 reports performance in BOPs (Business Operations Per Second). Higher values indicate better performance. Results are reported per warehouse count, producing a throughput curve.
When running with multiple JVMs (--nr-jvms > 1 or --max_jvms):
- A Controller process (
spec.jbb.Controller) is started first to coordinate the run. - Individual JBBmain processes are launched for each JVM instance.
- Each JVM handles a subset of the total warehouses (total warehouses / number of JVMs).
- Results from all JVMs are summed to produce the aggregate throughput.
The results directory contains:
- results_specjbb.csv: CSV file with warehouse counts, BOPs, and JVM configuration.
- results_specjbb.json: JSON output validated against the Pydantic schema.
- SPEC*.txt: Raw SPECjbb output files with detailed per-warehouse results.
- *.run.sh.out.*: Per-JVM output files with system metadata and benchmark results.
- test_results_report: File indicating test status ("Ran" or "Failed").
- meta_data*.yml: System metadata (CPU info, memory, NUMA topology, kernel version).
- PCP data (if --use_pcp option used): Performance Co-Pilot monitoring data.
Results are validated against the following Pydantic schema (results_schema.py):
| Field | Type | Constraint |
|---|---|---|
| Warehouses | int | > 0 |
| Bops | int | > 0 |
| Numb_JVMs | int | > 0 |
| Start_Date | datetime | required |
| End_Date | datetime | required |
./specjbb_runThis runs with:
- Java 21
- Automatic warehouse sizing based on CPU count
- 1 iteration
- 1 JVM
- No NUMA pinning
./specjbb_run --java_version 17Uses Java 17 instead of the default Java 21.
./specjbb_run --max_jvmsLaunches one JVM per NUMA node for optimal memory locality.
./specjbb_run --max_jvms --node_pinning yLaunches one JVM per NUMA node and binds each JVM to its corresponding NUMA node using numactl.
./specjbb_run --nr-jvms 4Runs with exactly 4 JVM instances.
./specjbb_run --start-warehouses 8 --stop-warehouses 128 --inc-warehouses 8Tests from 8 to 128 warehouses, incrementing by 8 each step.
./specjbb_run --iterations 3Runs the benchmark 3 times to check consistency.
./specjbb_run --regressionRuns with reduced settings: 120-second measurement, 8 warehouse data points. When combined with node counts, runs with 1 node and the maximum number of nodes.
./specjbb_run --use_pcpCollects Performance Co-Pilot data during the run.
./specjbb_run --specjbb_kit SPECjbb2005_kit_v1.07.tar.gzUses the specified kit archive from ~/uploads instead of auto-detecting the most recent one.
./specjbb_run --max_jvms --node_pinning y --java_version 21 --iterations 3 --use_pcpRuns one JVM per NUMA node with pinning, uses Java 21, runs 3 iterations, and collects PCP data.
The script automatically calculates SPECjbb warehouse parameters based on system hardware:
- Detects the number of logical CPUs in the system.
- Sets the ending warehouse count to 2x the logical CPU count.
- Can be overridden with
--stop-warehouses.
- For systems with > 16 CPUs: calculated to produce approximately 8 data points across the warehouse range.
All divisions use integer arithmetic (bash
bc), so results are truncated toward zero.increment = end_warehouse / 8 (integer division) start = (end_warehouse - (increment * 8)) + increment - For systems with <= 16 CPUs: starts at 2.
- Can be overridden with
--start-warehouses.
- For systems with > 16 CPUs:
end_warehouse / 8(integer division, truncated toward zero). - For systems with <= 16 CPUs: 2.
- Can be overridden with
--inc-warehouses.
When running with multiple JVMs, the warehouse parameters are divided by the number of JVMs:
- Each JVM runs
end_warehouse / nr_jvmswarehouses. - Increment and starting warehouses are similarly divided.
- Results are aggregated across JVMs during post-processing.
When --regression is used:
- Measurement time is set to 120 seconds.
- Increment is recalculated to produce exactly 8 data points.
- The benchmark is run with 1 node and the maximum number of nodes.
The wrapper automatically calculates the Java heap size based on system resources:
- Detects the total number of logical CPUs.
- Doubles the CPU count for the calculation basis (
wcpus = cpus * 2). - Calculates stack size using:
stack_size = (1 + ((wcpus / 256) / act_jvms)) * 8192 MiB - On systems with <= 256 CPUs per JVM, each JVM gets 8192 MiB of heap.
- On larger systems, heap scales proportionally to prevent premature termination.
- Both
-Xmsand-Xmxare set to the same value to avoid heap resizing overhead.
The script uses standardized error codes from test_tools error_codes:
- 0: Success
- 101: Git clone failure (test_tools repository)
- E_GENERAL: General execution errors (package installation failures, kit extraction failures, JVM launch failures).
- E_NO_ARGS: Missing required arguments
- E_PARSE_ARGS: Argument parsing failure
- E_USAGE: Invalid usage/arguments
A non-zero return code from verify_results indicates that the output data did not pass schema validation.
SPECjbb2005 is a licensed product from SPEC. The wrapper does not include the benchmark kit. You must obtain a license and upload the kit archive (SPECjbb2005_kit*.tar.gz) to ~/uploads before running the wrapper.
- x86_64: Full support for AMD and Intel CPUs.
- aarch64: Supported. The per-JVM launcher adjusts the thread stack size (
-Xss448kfor aarch64 vs.-Xss330kfor x86_64).
- Java 21 is the default and has the broadest OS support (RHEL, Ubuntu, SLES, Amazon Linux).
- Java 11 and 17 are supported on Ubuntu, SLES, and Amazon Linux (no RHEL package defined).
- Java 23 and 24 are only available on Amazon Linux (Corretto).
- Java 25 is only available on Ubuntu.
- Java 11 disables the
-XX:+AggressiveOptsJVM flag (deprecated in later versions).
- For multi-socket systems, running one JVM per NUMA node (
--max_jvms) typically improves performance by maintaining memory locality. - Adding
--node_pinning yfurther improves consistency by binding each JVM to its NUMA node vianumactl --membind --cpunodebind. - Single-node systems should use a single JVM (the default).
- Run multiple iterations to verify consistency.
- Ensure the system is idle (no other workloads) for best results.
- Consider the active tuned profile on RHEL systems.
- Use
--max_jvms --node_pinning yon multi-socket systems for optimal throughput. - The default warehouse range is designed to capture the throughput curve from low to high utilization.
The repository includes reduce_jbb.sh, a standalone post-processing tool. When you have multiple SPECjbb result files from separate runs, it:
- Combines all result files.
- For each warehouse count, sorts the BOPs values.
- Removes the highest and lowest values (trimmed mean).
- Averages the remaining values.
- Outputs the reduced data to
spec_sum.results.
Usage:
cd <directory_with_SPEC_txt_files>
/path/to/reduce_jbb.sh
cat spec_sum.results- If the SPECjbb kit is not found, verify it is placed in
~/uploadsand the filename begins withSPECjbb2005_kit. - If Java is not found, verify the correct version is installed and check the path in
/etc/alternatives/(RHEL) or/usr/lib/jvm/(Ubuntu). - If performance is unexpectedly low, check NUMA topology and consider using
--max_jvms --node_pinning y. - If JVMs terminate early on large systems, the wrapper should auto-scale the heap size, but you can verify by checking the stack_size calculation in the output.
- Use
--use_pcpto collect detailed performance counters for analysis. - For regression testing, use
--regressionto reduce run time while still producing meaningful results.