Observed since 20 Oct, 19:47 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
VLLM performance testing actuator for ado
This repository contains the vLLM ado actuator for benchmarking LLM inference
performance with vLLM. (For more about Actuators, what they represent, how to
create them etc., see the ado
docs).
The actuator implements a set of functionalities to deploy and run serving
benchmarks for different LLMs for vLLM. This actuator deploys
vLLM on to an
OpenShift
cluster and runs benchmarks using either vLLM's built-in benchmarking tool
(vllm bench serve)
or GuideLLM. The actuator is named
vllm_performance and provides thirteen experiments spanning standard LLM
benchmarking, agentic tool-calling, and geospatial model benchmarking.
This guide has two parts:
After running the exercise, please feel free to explore further and try a larger experiment.
[!NOTE]
These prerequisites must be fulfilled before you start with this actuator
- Access to an OpenShift cluster with at least 1 node with 1 available NVIDIA GPU. You will need access to a namespace with permissions for GPU-based deployments
- You will need to have downloaded and installed
adoaccording to this guide.
Ensure the virtual environment you installed ado into is active. Then, run:
pip install ado-vllm-performance
This will automatically install both vLLM and GuideLLM benchmarking tools, enabling all experiments:
vllm-bench-deployment and vllm-bench-endpoint (vLLM benchmarks)guidellm-bench-deployment and guidellm-bench-endpoint (GuideLLM
benchmarks)geospatial-vllm-bench-deployment and geospatial-vllm-bench-endpoint
(Geospatial model benchmarks with vLLM)geospatial-guidellm-bench-deployment and
geospatial-guidellm-bench-endpoint (Geospatial model benchmarks with
GuideLLM)geospatial-vllm-bench-deployment-custom-dataset and
geospatial-vllm-bench-endpoint-custom-dataset (Geospatial with custom
datasets using vLLM)geospatial-guidellm-bench-deployment-custom-dataset and
geospatial-guidellm-bench-endpoint-custom-dataset (Geospatial with custom
datasets using GuideLLM)For development from source:
pip install -e plugins/actuators/vllm_performance
from the root of the ado source repository. You can clone the repository with:
git clone https://github.com/IBM/ado.git
Confirm that the actuator is installed:
ado get actuators --details
You should see vllm_performance in the list. To confirm all experiments are
registered, run:
ado get experiments --details
The vllm_performance experiments you should see are:
vllm-bench-deploymentvllm-bench-endpointguidellm-bench-deploymentguidellm-bench-endpointtest-agentic-tool-callinggeospatial-vllm-bench-deploymentgeospatial-vllm-bench-endpointgeospatial-guidellm-bench-deploymentgeospatial-guidellm-bench-endpointgeospatial-vllm-bench-deployment-custom-datasetgeospatial-vllm-bench-endpoint-custom-datasetgeospatial-guidellm-bench-deployment-custom-datasetgeospatial-guidellm-bench-endpoint-custom-datasetYou can understand the constitutive properties required for the experiment and the target and observed properties measured by an experiment by running:
ado describe experiment vllm-bench-deployment
The experiment protocols for the vLLM actuator are defined in
ado_actuators/vllm_performance/experiments/performance_testing.yaml
and
ado_actuators/vllm_performance/experiments/performance_testing_geospatial.yaml.
You will need to update these if you want to modify the values that can be
accepted as valid for the input properties.
Before using the vLLM actuator to execute experiments, you must configure its parameters. First, get the template for the configuration:
ado template actuatorconfiguration --actuator-identifier vllm_performance \
-o actuatorconfiguration.yaml
This will create the actuatorconfiguration.yaml file, which will look like:
actuatorIdentifier: vllm_performance
metadata:
description: null
labels: null
name: null
parameters:
benchmark_retries: 3
deployment_template: null
developer_mode: false
free_environment_ttl: 300
gc_force_delete: false
gc_force_delete_threshold: 3
hf_token: ''
image_pull_secret_name: ''
in_cluster: false
max_environments: 1
namespace: null
node_selector: {}
otlp_traces_endpoint: null
pvc_name: null
pvc_template: null
retries_timeout: 5
service_template: null
verify_ssl: false
The three key parameters we have to set here are hf_token, namespace, and
node_selector.
hf_token: Access token from
HuggingFace.
namespace: The namespace you have access to in your OpenShift cluster.
node_selector: JSON dictionary representing a Kubernetes selector for a node
with available GPUs. Make sure it is formatted correctly, for example:
node_selector: {"kubernetes.io/hostname":"cpu16"}
We will discuss the other parameters later. Once you have put in the parameters, create the actuator configuration with:
ado create actuatorconfiguration -f vllm_performance_actuatorconfiguration.yaml
Note: You can have multiple configurations for an actuator.
To get started, we have provided an exercise to run a benchmarking experiment
for a single vLLM deployment configuration. The instructions for this exercise
assume you are running ado from a machine outside of the target
Kubernetes/OpenShift cluster.
[!NOTE]
Since this is an example exercise, we will use the
localcontext and thedefaultsample store.
To ensure the local context is active, run:
ado context local
ado uses the concept of
Discovery Spaces to
describe what to test (in this case vLLM workload configurations) and how to
test them (the vLLM benchmark(s) to run).
The set of configurations to test is defined by the entity space, and the set of experiments to perform by the measurement space.
An example discoveryspace for vLLM inference benchmarking can be found in
yamls/discoveryspace_override_defaults_small.yaml.
This defines a simple discovery space with four entities.
Our sample space will benchmark vLLM serving the LLM specified by model_name,
on a node (determined through node_selector) with a specific GPU
(NVIDIA-A100-80GB-PCIe) specified in gpu_type.
[!NOTE]
Ensure that the GPU specified in
gpu_typeis present on the node. To find out the gpu model of your selected node, try the following command:oc describe node <node name> | grep "nvidia.com/gpu.product"If this returns a different GPU model, then you must update the experiment protocol.
Create the discoveryspace:
ado create space -f yamls/discoveryspace_override_defaults_small.yaml \
--use-default-sample-store
Before we run any experiment, we can see that the discoveryspace is empty:
ado show measurements space --use-latest
Will output:
Nothing was returned for entity type matching and property format observed in space space-c81773-default.
To see all the entities (parameter combinations) that are waiting to be measured, try executing:
ado show measurements space --include missing --use-latest
The output will look like:
┌───────┬────────────────┬────────────────┬────────┬────────┬───────┬─────────────┬──────────────┬────────────────┬────────────────┬─────────────┬─────────────────┬─────────────┬────────┬────────────────┐
│ INDEX │ model │ image │ n_cpus │ memory │ dtype │ num_prompts │ request_rate │ max_concurren… │ gpu_memory_ut… │ cpu_offload │ max_batch_toke… │ max_num_seq │ n_gpus │ gpu_type │
├───────┼────────────────┼────────────────┼────────┼────────┼───────┼─────────────┼──────────────┼────────────────┼────────────────┼─────────────┼─────────────────┼─────────────┼────────┼────────────────┤
│ 0 │ meta-llama/Ll… │ quay.io/datap… │ 8 │ 128Gi │ auto │ 100 │ 100 │ 100 │ 0.9 │ 0 │ 16384 │ 256 │ 1 │ NVIDIA-A100-8… │
│ 1 │ meta-llama/Ll… │ quay.io/datap… │ 8 │ 128Gi │ auto │ 100 │ 100 │ 100 │ 0.9 │ 0 │ 32768 │ 256 │ 1 │ NVIDIA-A100-8… │
│ 2 │ meta-llama/Ll… │ quay.io/datap… │ 8 │ 128Gi │ auto │ 250 │ 100 │ 100 │ 0.9 │ 0 │ 16384 │ 256 │ 1 │ NVIDIA-A100-8… │
│ 3 │ meta-llama/Ll… │ quay.io/datap… │ 8 │ 128Gi │ auto │ 250 │ 100 │ 100 │ 0.9 │ 0 │ 32768 │ 256 │ 1 │ NVIDIA-A100-8… │
└───────┴────────────────┴────────────────┴────────┴────────┴───────┴─────────────┴──────────────┴────────────────┴────────────────┴─────────────┴─────────────────┴─────────────┴────────┴────────────────┘
Which is the entity we want to measure.
First, log in to your OpenShift cluster and select your assigned namespace
oc login <your OpenShift API endpoint>
oc project <your assigned namespace>
Next, we'll set up the operation to measure our entity defined above.
In ado parlance, measurements are executed through operations which
represent the executions of experiments on entities.
An example of an operation can be found in
yamls/random_walk_operation.yaml.
You can run the operation using the actuator configuration and space that we
have created earlier with:
ado create operation -f yamls/random_walk_operation.yaml \
--use-latest space --use-latest actuatorconfiguration
ado will initialise a local Ray cluster and starts the measurement at the
point where these lines appear:
...
=========== Starting Discovery Operation ===========
(RandomWalk pid=79429) 'all' specified for number of entities to sample. This is 4 entities - the size of the entity space
...
The actuator uses the entity to create a vLLM deployment, followed by execution of the benchmark script. This process will take some time as it involves downloading the container image from Quay and the model from HuggingFace, both of which are network-intensive. You can monitor if the deployment is ready by executing the following in another shell:
oc get deployments --watch
The experiment is successfully completed if the ado output is similar to the
following:
(RandomWalk pid=46852) Continuous Batching: EXPERIMENT COMPLETION. Received finished notification for experiment in measurement request in group 0: request-4332aa-experiment-performance-testing-entities-model.ibm-granite/granite-3.3-8b-instruct-image.quay.io/dataprep1/data-prep-kit/vllm_image:0.1-n_cpus.8-memory.128Gi-dtype.auto-num_prompts.500-request_rate.-1-max_concurrency.-1-gpu_memory_utilization.0.9-cpu_offload.0-max_batch_tokens.16384-max_num_seq.256-n_gpus.1-gpu_type.NVIDIA-A100-80GB-PCIe (explicit_grid_sample_generator)-requester-randomwalk-0.9.7.dev10+b7a010dd.dirty-42ad60-time-2025-08-11 15:53:54.137571+01:00
(RandomWalk pid=46852) Continuous batching: GET EXPERIMENT. No new experiments in queue. Requests made: 1. Experiments Completed: 1
If the output contains EXPERIMENT FAILURE, then something has gone wrong.
Verify that the entity has been measured by running:
ado show measurements space --use-latest -o csv --output-file entities.csv
The csv file will have one line representing the entity featuring values for all
its measured properties
(performance-testing-output_throughput,performance-testing-total_token_throughput,performance-testing-mean_ttft_ms,
etc.)
Congratulations! You have successfully executed the vLLM benchmark on a vLLM
workload configuration using ado!
vLLM testing implementation is based on this
guide which is using
benchmark_serving.py
to implement the actual benchmarking. The benchmarking is done using HTTP
requests using vLLM OpenAI API server.
To use this approach it is necessary to:
This figure shows the outline of the components and the parameters available for configuring each of them

The test results in the figure are the measurements recorded for the entity. The deployment parameters form the configuration space. Test parameters are partially inferred from the configuration space and partially from the context (Kubernetes endpoints, etc.)
The vLLM actuator includes support for benchmarking geospatial models, specifically IBM-NASA Prithvi models for Earth observation tasks.
Geospatial experiments are available for both endpoint and deployment testing, with support for pre-packaged datasets (india_url_in_b64_out, valencia_url_in_b64_out) and custom datasets. For detailed information on geospatial experiments, dataset formats, and usage examples, see the vLLM Performance Geospatial documentation.
The actuator package is under ado_actuators/vllm_performance. Note all
actuator packages should be placed under a directory called ado_actuators as
this is the name of package that contains all ado plugins.
The key files are:
Entry point registration in pyproject.toml
Registers the actuator class with ado using Python entry points.
Example:
[project.entry-points."ado.actuators"]
vllm_performance = "ado_actuators.vllm_performance.actuator:VLLMPerformanceTest"
actuator.py
ActuatorBase and define an identifier
attribute.experiments.yaml
experiment_executor.py (OPTIONAL)
The actuator is configured using VLLMPerformanceTestParameters class
You can customise deployment_template, service_template and pvc_template
for your OpenShift/K8s cluster. Refer to the
default yamls for the
templates referred to in Configuring the actuator
and modify them appropriately
If you create a custom Docker image and upload it to a repository, please do not
forget to create a corresponding Image pull secret in your assigned namespace.
You must also update the value of the image_pull_secret_name parameter of the
actuator configuration.
By default, vLLM deployments that finish an experiment are kept in a free pool for up to 5 minutes so that subsequent experiments sharing the same deployment configuration can reuse them rather than paying the full start-up cost.
Three parameters control this behaviour:
free_environment_ttl (default: 300): Time-to-live in seconds for idle
(free) Kubernetes environments. When an environment has been idle for at
least this many seconds the garbage-collector deletes it. Set to 0 to
delete every environment immediately upon release (disables the free pool).
gc_force_delete (default: false): When true, the garbage-collector
issues a force-delete (clears Kubernetes finalizers and uses
grace_period_seconds=0) for any deployment that is still present in
Kubernetes after gc_force_delete_threshold GC cycles following a normal
delete. When false (the default) the GC logs a warning each cycle and
keeps waiting for the deployment to disappear naturally.
gc_force_delete_threshold (default: 3): Number of GC cycles a deployment
may remain present in Kubernetes after a delete has been issued before a
force-delete is triggered. Only used when gc_force_delete is true.
The values for the parameters in the entity space must be a subset of the acceptable values defined for the experiment (the experiment protocol). Therefore, depending on your environment and use case, you may need to update the set of values to expand the configuration space being studied.
For example, you may want to benchmark a different LLM or you may want to change
the GPU type to the one installed in your cluster. In the former case, you will
add values to model and in the latter case, you will have to modify the
domain of the gpu_type parameter to avoid validation errors.
To do this, open the
experiment definition YAML file
in a text editor, and add your GPU model to the list of values of gpu_type.
Then, reinstall this actuator by running:
pip install .
After that, you can use the new value of gpu_type in your experiments. For
example, in
the sample space definition file,
the location to update will be:
- identifier: "gpu_type"
propertyDomain:
values: ["NVIDIA-A100-80GB-PCIe"]
VLLM testing is using external environment (deployment + service) to run tests. Creating such an environment is resource-intensive. To speed up experiments execution it is recommended to use group samplers for running VLLM testing. This allows to create an environment once and use it for all experiments that can be used for it. In this case the group definition looks as follows:
grouping:
- model
- image
- n_gpus
- gpu_type
- n_cpus
- memory
- max_batch_tokens
- gpu_memory_utilization
- dtype
- cpu_offload
- max_num_seq
For the complete example of configuring random walk operation for the group samplers, look here
Try:
max_batch_tokens)pypistats · 87 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-19 – 2026-10-19 | 20 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-18 – 2026-10-18 | 20 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-17 – 2026-10-17 | 49 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-16 – 2026-10-16 | 23 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-15 – 2026-10-15 | 34 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-14 – 2026-10-14 | 96 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-13 – 2026-10-13 | 76 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-12 – 2026-10-12 | 50 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-11 – 2026-10-11 | 15 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-10 – 2026-10-10 | 17 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-09 – 2026-10-09 | 13 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-08 – 2026-10-08 | 74 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-07 – 2026-10-07 | 6 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-06 – 2026-10-06 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-05 – 2026-10-05 | 5 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-04 – 2026-10-04 | 4 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-03 – 2026-10-03 | 1 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-02 – 2026-10-02 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-10-01 – 2026-10-01 | 5 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-30 – 2026-09-30 | 13 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-29 – 2026-09-29 | 23 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-28 – 2026-09-28 | 25 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-27 – 2026-09-27 | 15 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-26 – 2026-09-26 | 9 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-25 – 2026-09-25 | 15 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-24 – 2026-09-24 | 41 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-23 – 2026-09-23 | 7 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-22 – 2026-09-22 | 6 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-21 – 2026-09-21 | 35 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-20 – 2026-09-20 | 5 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-19 – 2026-09-19 | 67 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-18 – 2026-09-18 | 16 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-17 – 2026-09-17 | 1 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-16 – 2026-09-16 | 39 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-15 – 2026-09-15 | 84 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-14 – 2026-09-14 | 117 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-13 – 2026-09-13 | 25 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-12 – 2026-09-12 | 2 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-11 – 2026-09-11 | 5 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-09 – 2026-09-09 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-08 – 2026-09-08 | 4 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-07 – 2026-09-07 | 11 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-05 – 2026-09-05 | 1 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-04 – 2026-09-04 | 7 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-03 – 2026-09-03 | 7 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-02 – 2026-09-02 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-09-01 – 2026-09-01 | 12 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-31 – 2026-08-31 | 17 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-30 – 2026-08-30 | 4 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-29 – 2026-08-29 | 8 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-28 – 2026-08-28 | 78 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-27 – 2026-08-27 | 47 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-26 – 2026-08-26 | 5 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-25 – 2026-08-25 | 2 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-24 – 2026-08-24 | 14 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-23 – 2026-08-23 | 10 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-22 – 2026-08-22 | 46 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-21 – 2026-08-21 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-20 – 2026-08-20 | 2 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-19 – 2026-08-19 | 2 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-18 – 2026-08-18 | 17 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-17 – 2026-08-17 | 20 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-16 – 2026-08-16 | 10 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-15 – 2026-08-15 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-14 – 2026-08-14 | 9 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-13 – 2026-08-13 | 5 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-11 – 2026-08-11 | 15 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-10 – 2026-08-10 | 15 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-09 – 2026-08-09 | 13 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-08 – 2026-08-08 | 18 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-07 – 2026-08-07 | 89 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-06 – 2026-08-06 | 25 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-05 – 2026-08-05 | 16 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-04 – 2026-08-04 | 95 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-03 – 2026-08-03 | 17 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-02 – 2026-08-02 | 22 | 2026-10-20T23:29:40.4784259Z |
| 2026-08-01 – 2026-08-01 | 20 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-31 – 2026-07-31 | 10 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-30 – 2026-07-30 | 25 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-29 – 2026-07-29 | 385 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-28 – 2026-07-28 | 10 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-27 – 2026-07-27 | 135 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-26 – 2026-07-26 | 4 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-25 – 2026-07-25 | 2 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-24 – 2026-07-24 | 3 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-23 – 2026-07-23 | 89 | 2026-10-20T23:29:40.4784259Z |
| 2026-07-22 – 2026-07-22 | 5 | 2026-10-20T23:29:40.4784259Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 1.16.0 | 20 Oct 2026 | 6 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:47 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:26c3d489bf4acb4adadaec5928d580950f13c2c1bd6233bf19e8a367f88193c6