# Benchmark Redis performance on Cobalt 100

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/servers-and-cloud-computing/redis-cobalt/)
- [Understand Redis on Azure Cobalt 100](https://learn.arm.com/learning-paths/servers-and-cloud-computing/redis-cobalt/background/)
- [Create an Azure Cobalt 100 Arm64 virtual machine](https://learn.arm.com/learning-paths/servers-and-cloud-computing/redis-cobalt/instance/)
- [Install Redis and build messaging pipelines](https://learn.arm.com/learning-paths/servers-and-cloud-computing/redis-cobalt/deploy-redis-cobalt/)
- [Benchmark Redis performance on Cobalt 100](https://learn.arm.com/learning-paths/servers-and-cloud-computing/redis-cobalt/redis-benchmark-and-validation/)
- [Next Steps](https://learn.arm.com/learning-paths/servers-and-cloud-computing/redis-cobalt/_next-steps/)

## Validate Redis for production workloads
In this section you implement production-grade event processing using Redis Streams consumer groups, simulate real workloads using Python, and benchmark Redis performance on an Azure Cobalt 100 Arm-based virtual machine.

You will validate Redis for high-throughput, low-latency workloads on Arm infrastructure.

## Create a consumer group
Consumer groups enable scalable and reliable message processing by distributing work across multiple consumers.

Terminal 1 is still running the Redis server. Use Terminal 2 or Terminal 3 from the previous section, which already has the Redis CLI open. If you closed those sessions, open a new terminal and start the CLI:
```
cd /tmp/redis-stable
src/redis-cli
```
At the `127.0.0.1:6379>` prompt, create a consumer group on the existing stream:
```
XGROUP CREATE mystream mygroup 0 MKSTREAM
```
The output is similar to:
```
__output__ OK
```

## Consume messages using a consumer group
At the `127.0.0.1:6379>` prompt, read messages from the stream as part of the consumer group:
```
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
```
The output is similar to:
```
__output__ 1) 1) "mystream"
__output__ 2) 1) 1) "1774931844279-0"
__output__ 2) 1) "user"
__output__ 2) "jack"
__output__ 3) "action"
__output__ 4) "login"
```

## Acknowledge processed messages
Acknowledge messages after processing to prevent re-delivery. Use the message ID returned in the `XREADGROUP` output above — for example `1774931844279-0`:
```
XACK mystream mygroup 1774931844279-0
```
The output is similar to:
```
__output__ (integer) 1
```
A return value of `1` confirms the message was acknowledged successfully.

Exit the Redis CLI before continuing:
```
QUIT
```

## Install Python Redis client
Install the Python venv module and create a virtual environment, then install the Redis client library:
```
sudo apt install -y python3-venv
python3 -m venv ~/redis-venv
source ~/redis-venv/bin/activate
pip install redis
```
The virtual environment remains active for the rest of this section. Your prompt will show `(redis-venv)` to confirm it is active.

## Create a Python producer
Create a producer script to send events to the Redis stream. Save the following code in a file named `producer.py`:
```python
import redis

r = redis.Redis(host='localhost', port=6379)

for i in range(10):
    r.xadd("mystream", {"event": f"msg-{i}"})
    print(f"Produced msg-{i}")
```
Run the producer:
```
python producer.py
```
The output is similar to:
```
__output__ Produced msg-0
__output__ Produced msg-1
__output__ ...
__output__ Produced msg-9
```

## Create a Python consumer
Create a consumer script to read and process messages. Save the following code in a file named `consumer.py`:
```python
import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

while True:
    messages = r.xreadgroup("mygroup", "consumer1", {"mystream": ">"}, count=1, block=5000)

    for stream, msgs in messages:
        for msg_id, data in msgs:
            print(f"Consumed {msg_id}: {data}")
            r.xack("mystream", "mygroup", msg_id)
```

### Run the consumer
```
python consumer.py
```
The output is similar to:
```
__output__ Consumed 1774931858864-0: {'user': 'yan', 'action': 'purchase'}
__output__ Consumed 1774935598721-0: {'event': 'msg-0'}
__output__ Consumed 1774935598721-1: {'event': 'msg-1'}
__output__ Consumed 1774935598721-2: {'event': 'msg-2'}
__output__ Consumed 1774935598721-3: {'event': 'msg-3'}
__output__ Consumed 1774935598722-0: {'event': 'msg-4'}
__output__ Consumed 1774935598722-1: {'event': 'msg-5'}
__output__ Consumed 1774935598722-2: {'event': 'msg-6'}
__output__ Consumed 1774935598722-3: {'event': 'msg-7'}
__output__ Consumed 1774935598722-4: {'event': 'msg-8'}
__output__ Consumed 1774935598722-5: {'event': 'msg-9'}
```
The consumer blocks for 5 seconds when no new messages arrive and then checks again. Press Ctrl+C to stop it when you’re done.

## Benchmark Redis performance
Run the Redis benchmark tool to measure throughput and latency:
```
cd /tmp/redis-stable
src/redis-benchmark -q -n 100000 -c 50
```
The output is similar to:
```
__output__ PING_INLINE: 132978.73 requests per second, p50=0.191 msec
__output__ PING_MBULK: 131752.31 requests per second, p50=0.191 msec
__output__ SET: 132802.12 requests per second, p50=0.191 msec
__output__ GET: 133689.83 requests per second, p50=0.191 msec
__output__ INCR: 131926.12 requests per second, p50=0.191 msec
__output__ LPUSH: 131406.05 requests per second, p50=0.191 msec
__output__ RPUSH: 130548.30 requests per second, p50=0.199 msec
__output__ LPOP: 131061.59 requests per second, p50=0.191 msec
__output__ RPOP: 135685.22 requests per second, p50=0.191 msec
__output__ SADD: 135869.56 requests per second, p50=0.191 msec
__output__ HSET: 136612.02 requests per second, p50=0.191 msec
__output__ SPOP: 134952.77 requests per second, p50=0.191 msec
__output__ ZADD: 136798.91 requests per second, p50=0.191 msec
__output__ ZPOPMIN: 134952.77 requests per second, p50=0.191 msec
__output__ LPUSH (needed to benchmark LRANGE): 136425.66 requests per second, p50=0.191 msec
__output__ LRANGE_100 (first 100 elements): 75357.95 requests per second, p50=0.335 msec
__output__ LRANGE_300 (first 300 elements): 31645.57 requests per second, p50=0.791 msec
__output__ LRANGE_500 (first 500 elements): 22036.14 requests per second, p50=1.127 msec
__output__ LRANGE_600 (first 600 elements): 19109.50 requests per second, p50=1.295 msec
__output__ MSET (10 keys): 137931.03 requests per second, p50=0.215 msec
__output__ XADD: 136425.66 requests per second, p50=0.191 msec
```
These results demonstrate high throughput and efficient performance on the Arm architecture.

### Arm64 performance analysis
The benchmark results highlight the strong performance characteristics of Redis on Azure Cobalt 100 Arm64 infrastructure:
- **High throughput:** Redis consistently achieves **130K–136K** operations per second across multiple commands.
- **Low latency:** Median latency remains around **~0.19 ms**, ensuring near real-time responsiveness.
- **Efficient stream ingestion:** XADD operations reach **~136K ops/sec**, making Redis Streams suitable for high-ingestion event pipelines.
- **Stable performance across workloads:** Consistent performance across **SET, GET, HASH, and STREAM operations** demonstrates efficient CPU and memory utilization on Arm.

These results validate that Arm-based infrastructure can handle high-performance, low-latency data workloads effectively.

## Benchmark Pub/Sub performance
Run a publish benchmark to evaluate messaging throughput:
```
cd /tmp/redis-stable
src/redis-benchmark -t publish -n 100000
```
**Note**: The Redis benchmark tool does not display detailed output for Pub/Sub operations. To validate Pub/Sub behavior, use a subscriber or monitor Redis metrics using the INFO command.

## Monitor Redis metrics
Open a new terminal and use the Redis INFO command to inspect runtime statistics:
```
cd /tmp/redis-stable
src/redis-cli info stats
```
The output is similar to:
```
__output__ # Stats
__output__ total_connections_received:1058
__output__ total_commands_processed:2300074
__output__ instantaneous_ops_per_sec:0
__output__ total_net_input_bytes:129526426
__output__ total_net_output_bytes:1373991650
__output__ total_net_repl_input_bytes:0
__output__ total_net_repl_output_bytes:0
__output__ instantaneous_input_kbps:0.00
__output__ instantaneous_output_kbps:0.00
__output__ instantaneous_input_repl_kbps:0.00
__output__ instantaneous_output_repl_kbps:0.00
__output__ rejected_connections:0
__output__ sync_full:0
__output__ sync_partial_ok:0
__output__ sync_partial_err:0
__output__ expired_subkeys:0
__output__ expired_subkeys_active:0
__output__ expired_keys:0
__output__ expired_keys_active:0
__output__ expired_stale_perc:0.00
__output__ expired_time_cap_reached_count:0
__output__ expire_cycle_cpu_milliseconds:65
__output__ evicted_keys:0
__output__ evicted_clients:0
__output__ evicted_scripts:0
__output__ total_eviction_exceeded_time:0
__output__ current_eviction_exceeded_time:0
__output__ keyspace_hits:800087
__output__ keyspace_misses:0
__output__ pubsub_channels:0
__output__ pubsub_patterns:0
__output__ pubsubshard_channels:0
__output__ latest_fork_usec:430
__output__ total_forks:3
__output__ migrate_cached_sockets:0
__output__ slave_expires_tracked_keys:0
__output__ active_defrag_hits:0
__output__ active_defrag_misses:0
__output__ active_defrag_key_hits:0
__output__ active_defrag_key_misses:0
__output__ total_active_defrag_time:0
__output__ current_active_defrag_time:0
__output__ tracking_total_keys:0
__output__ tracking_total_items:0
__output__ tracking_total_prefixes:0
__output__ unexpected_error_replies:0
__output__ total_error_replies:0
__output__ dump_payload_sanitizations:0
__output__ total_reads_processed:2301131
__output__ total_writes_processed:2300077
__output__ io_threaded_reads_processed:0
__output__ io_threaded_writes_processed:0
__output__ io_threaded_total_prefetch_batches:0
__output__ io_threaded_total_prefetch_entries:0
__output__ client_query_buffer_limit_disconnections:0
__output__ client_output_buffer_limit_disconnections:0
__output__ reply_buffer_shrinks:167
__output__ reply_buffer_expands:0
__output__ eventloop_cycles:1973082
__output__ eventloop_duration_sum:24187445
__output__ eventloop_duration_cmd_sum:4769476
__output__ instantaneous_eventloop_cycles_per_sec:9
__output__ instantaneous_eventloop_duration_usec:142
__output__ acl_access_denied_auth:0
__output__ acl_access_denied_cmd:0
__output__ acl_access_denied_key:0
__output__ acl_access_denied_channel:0
```

### Key observations
- Redis achieves **~130K+ ops/sec** on Arm64
- Latency remains under **1 millisecond**
- No rejected connections during load
- Streams provide reliable and scalable messaging
- System remains stable under high throughput

## What you’ve learned
You have successfully:
- Implemented consumer groups for scalable processing
- Built Python-based producer and consumer applications
- Benchmarked Redis performance on Cobalt 100
- Validated Redis for high-throughput workloads
