How to Benchmark a Raspberry Pi Using Vcgencmd

Vcgencmd
(Image credit: Tom's Hardware)

The vcgencmd has been buried deep in Raspberry Pi OS for many years, but it took the Raspberry Pi 5 for us to truly learn to love it. At its most basic level, the command is used to output information from the VideoCore GPU, which forms part of the SoC. But with a few extra options / arguments we can get live CPU temperature data, voltages, clock speeds for many different components and much more. 

In this how to we will introduce the basic usage of the command and then write a custom Bash script which will benchmark any Raspberry Pi system.

Basic Usage of Vcgencmd

The command has multiple options to measure clock speeds, temperatures, voltages etc. Let's go through them and see how each command is used, and an example of its output.

Measure Clock Speeds

Every computer has more than one clock speed. The CPU may be running in the Gigahertz, but some parts of your computer will be running at much lower speeds. The vcgencmd command has options to monitor

Swipe to scroll horizontally
DescriptionCommandExample Output
Get Arm CPU core speedvcgencmd measure_clock armfrequency(0)=1500004352
Get GPU core speedvcgencmd measure_clock corefrequency(0)=500001504
Get H.264 block speedvcgencmd measure_clock h264frequency(0)=0
Get image sensor pipeline speedvcgencmd measure_clock ispfrequency(0)=500000672
Get 3D block speedvcgencmd measure_clock v3dfrequency(0)=500001504
Get UART speedvcgencmd measure_clock uartfrequency(0)=43999120
Get PWM block (analog audio output)vcgencmd measure_clock pwmfrequency(0)=0 (Raspberry Pi 5 has analog video out, but no audio)
Get SD card interface clock speedvcgencmd measure_clock emmcfrequency(0)=200000432
Get pixel valuesvcgencmd measure_clock pixelfrequency(0)=107999800
Get analogue video encoder speedvcgencmd measure_clock vecfrequency(0)=0
Get HDMI clockvcgencmd measure_clock hdmifrequency(0)=648002816
Get display parallel interface clock speedvcgencmd measure_clock dpifrequency(0)=0

Measure Voltages

Using vcgencmd, we can measure the voltages of the VideoCore chip, RAM and the voltages, currents in use on the many power sources, including the Power Management IC (PMIC).

Swipe to scroll horizontally
DescriptionCommandExample Output
Get VideoCore voltagevcgencmd measure_volts corevolt=0.7200V
Get RAM core voltagevcgencmd measure_volts sdram_cvolt=0.6000V
Get RAM I/O voltagevcgencmd measure_volts sdram_ivolt=0.6000V
Get RAM Phy voltagevcgencmd measure_volts sdram_pvolt=1.1000V
Read PMIC voltagesvcgencmd pmic_read_adc3V7_WL_SW_A current(0)=0.00390372A 3V3_SYS_A current(1)=0.05562801A 1V8_SYS_A current(2)=0.16493220A DDR_VDD2_A current(3)=0.02049453A DDR_VDDQ_A current(4)=0.00000000A 1V1_SYS_A current(5)=0.18152300A 0V8_SYS_A current(6)=0.32693650A VDD_CORE_A current(7)=0.71440000A 3V3_DAC_A current(17)=0.48840000A 3V3_ADC_A current(18)=0.42735000A 1V1_SYS_A current(16)=5.55555000A HDMI_A current(22)=0.02344320A 3V7_WL_SW_V volt(8)=3.71462400V 3V3_SYS_V volt(9)=3.31096100V 1V8_SYS_V volt(10)=1.79926600V DDR_VDD2_V volt(11)=1.11355200V DDR_VDDQ_V volt(12)=0.60842430V 1V1_SYS_V volt(13)=1.10622600V 0V8_SYS_V volt(14)=0.80476110V VDD_CORE_V volt(15)=0.72097620V 3V3_DAC_V volt(20)=3.30768900V 3V3_ADC_V volt(21)=3.30494200V 1V1_SYS_V volt(19)=0.79765500V HDMI_V volt(23)=5.10004000V EXT5V_V volt(24)=5.09602000V BATT_V volt(25)=0.00683760V
Selective output of PMIC values. Find the value that you want from the list, add it as an argument.vcgencmd pmic_read_adc EXT5V_VEXT5V_V volt(24)=5.12416000V

System Throttle Status

When the Raspberry Pi hits around 80 degrees Celsius, it will enter thermal throttle. This reduces the speed of the CPU in an attempt to keep it cool. When running benchmarks we need to know if a CPU is throttled, and vcgencmd has the command to tell us that.

Swipe to scroll horizontally
DescriptionCommandExample Output
Returns the system’s throttle state as a bit-pattern.vcgencmd get_throttledthrottled=0x0
Row 1 - Cell 0 Row 1 - Cell 1 Row 1 - Cell 2

System Throttle Status Bit Table

Swipe to scroll horizontally
DescriptionBitHex Value
Under-voltage detected00x1
Arm frequency capped10x2
Currently throttled20x4
Soft temperature limit active30x8
Under-voltage has occurred160x10000
Arm frequency capping has occurred170x20000
Throttling has occurred180x40000
Soft temperature limit has occurred190x80000

System Configuration Info with Vcgencmd

The vcgencmd can be used to inspect and dump the current system configuration. By default, the output is directed to the standard output (the terminal) but using a pipe the output can be redirected to a file for comparison.

Swipe to scroll horizontally
DescriptionCommandExample Output
Returns system configurationvcgencmd get_config intarm_64bit=1 arm_boost=1 arm_freq=2400 arm_freq_min=1000 arm_peri_high=1 audio_pwm_mode=2 auto_initramfs=1 camera_auto_detect=1 core_freq=910 core_freq_min=500 disable_commandline_tags=2 disable_fw_kms_setup=1 disable_l2cache=1 disable_overscan=1 display_auto_detect=1 display_default_lcd=-1 display_hdmi_rotate=-1 display_lcd_rotate=-1 dvfs=4 enable_gic=1 enable_uart=-1 force_eeprom_read=1 force_pwm_open=1 framebuffer_depth=16 framebuffer_ignore_alpha=1 framebuffer_swap=1 gpu_freq_min=500 hdmi_enable_4kp60=1 hevc_freq =910 hevc_freq_min=500 ignore_lcd=-1 init_uart_clock=0x2dc6c00 isp_freq=910 isp_freq_min=500 mask_gpu_interrupt1=16418 max_framebuffers=2 over_voltage_avs=0x20404 pause_burst_frames=1 program_serial_random=1 total_mem=8192 usb_max_current_enable=1 v3d_freq=960 v3d_freq_min=500 vpred=8921 hdmi_force_cec_address:0=65535 hdmi_force_cec_address:1=65535
Returns memory split for Arm CPUvcgencmd get_mem armarm=1020M
Returns memory split for GPUvcgencmd get_mem gpugpu=4M Note: For Pi 5 this seems to be dynamically allocated.

A Simple Benchmarking Script with Vcgencmd

With our knowledge of vcgencmd and Bash scripting we can make a simple benchmarking tool that will take a CPU temperature, speed and throttle status reading every 60 seconds and then store the details in a CSV file. 

The script is split into three sections. A 60-second idle temperature reading which gives a baseline to reference from. The second part is the stress test itself, using stress to push all four cores for five minutes. Finally we repeat the idle period for 60-seconds to show the CPU cooling down.

We’re going to write this script on a Raspberry Pi 5, but the same script will work on all models of Raspberry Pi.

1. Open a terminal and update the software repositories and then install stress. Stress is a command line tool to stress test CPUs.

sudo apt update && sudo apt install stress

2. From the main Raspberry Pi desktop menu select Programing >> Geany. Geany is a great and lightweight text editor for coding.

3. Tell the script where to find the system shell. This has the name “shabang” a concatenation of sharp (#) and bang (!).

#!/bin/bash

4. Output a message to the shell, informing the user of what the application will do. Then create a variable to store the name of the output file. This should be a CSV file, but the name can be your choosing.

echo "Tom's Hardware Benchmark Tool"
output_file="benchmark.csv"

5. Create a header for the CSV file and write to the file. This will set the column headings in the CSV file and spreadsheet.

echo "Timestamp,CPU Temperature (°C),CPU Clock Speed (MHz),CPU Throttled" > "$output_file"

6. Output a message to say that the application will idle for 60 seconds.

echo "Idle data for 60 seconds"

7. Create a for loop that will iterate 60 times.

for i in {1..60}; do

8. Write the current time to a variable, then print the timestamp to the shell.

   timestamp=$(date +"%Y-%m-%d %H:%M:%S")
   echo "$timestamp"

9. Use vcgencmd to get the current CPU temperature, cut out any information except for the temperature and save to a variable. Then echo the temperature to the shell. If we don’t do this then we will have to sanitize the data in the CSV file, but right now we can automate its removal.

   cpu_temp=$(vcgencmd measure_temp | cut -d= -f2 | cut -d\' -f1)
   echo "$cpu_temp"

10. Using vcgencmd, get the current CPU speed in MHz, save it to a variable and then print the speed to the shell. We have to slice the speed from the output of the command and then divide by 1.000,000 to get the speed in MHz.

   cpu_clock_speed=$(($(vcgencmd measure_clock arm | awk -F= '{print $2}') / 1000000))
   echo "$cpu_clock_speed"

11. Check if the CPU has been throttled, save the data to a variable and print to the shell. This will return a bit pattern, please refer to the table to decode.

   throttled_status=$(vcgencmd get_throttled)
   echo "$throttled_status"

12. Echo a series of # to the shell. This will help break the data into sections when it prints across the terminal window.

   echo "################"

13. Write the data to the CSV file. Note that we use >> to append the data to the CSV file. If there were only a single > it would be overwritten.

   echo "$timestamp,$cpu_temp,$cpu_clock_speed,$throttled_status" >> "$output_file"

14. Still inside the for loop, pause for one second and then close the for loop. The code in the for loop will write 60 readings to the CSV file, one per second of the idle time.

   sleep 1
done

15. Call the stress command to run a stress test on all four CPU cores for 300 seconds (five minutes). The “&” will place the command in the background and not block our script from running.

stress --cpu 4 -t 300 &

16. Echo (print) a message to say that the stress test is now starting.

echo "Stress data for 300 seconds"

17. We repeat the for loop from before, simply change the 60 to 300 and then record the same temperature, CPU speed and throttle status to the variables and then write to the CSV file.

for i in {1..300}; do
   timestamp=$(date +"%Y-%m-%d %H:%M:%S")
   echo "$timestamp"
   cpu_temp=$(vcgencmd measure_temp | cut -d= -f2 | cut -d\' -f1)
   echo "$cpu_temp"
   cpu_clock_speed=$(($(vcgencmd measure_clock arm | awk -F= '{print $2}') / 1000000))
   echo "$cpu_clock_speed"
   throttled_status=$(vcgencmd get_throttled)
   echo "$throttled_status"
   echo "################"
   echo "$timestamp,$cpu_temp,$cpu_clock_speed,$throttled_status" >> "$output_file"
   # Sleep for 1 second
   sleep 1
done

18. The final section is a cool down period, allowing the CPU to go back to normal. This is the same loop as the idle period.

echo "Cool down data for 60 seconds"
for i in {1..60}; do
   # Get current timestamp
   timestamp=$(date +"%Y-%m-%d %H:%M:%S")
   echo "$timestamp"
   # Get CPU temperature in degrees Celsius
   cpu_temp=$(vcgencmd measure_temp | cut -d= -f2 | cut -d\' -f1)
   echo "$cpu_temp"
   # Get CPU clock speed in MHz
   cpu_clock_speed=$(($(vcgencmd measure_clock arm | awk -F= '{print $2}') / 1000000))
   echo "$cpu_clock_speed"
   # Check if the CPU is throttled
   throttled_status=$(vcgencmd get_throttled)
   echo "$throttled_status"
   echo "################"
   # Append data to CSV file
   echo "$timestamp,$cpu_temp,$cpu_clock_speed,$throttled_status" >> "$output_file"
   # Sleep for 1 second
   sleep 1
done

19. Save the code as benchmark.sh to your home directory.

20. In a terminal, make the file executable.

chmod +x benchmark.sh

21. From the terminal, run the code and wait for the benchmark to complete.

./benchmark.sh

22. Import the CSV file into a spreadsheet and use it to produce graphs / tables of your findings.

Complete Code Listing

#!/bin/bash
echo "Tom's Hardware Benchmark Tool"
output_file="benchmark.csv"


echo "Timestamp,CPU Temperature (°C),CPU Clock Speed (MHz),CPU Throttled" > "$output_file"
echo "Idle data for 60 seconds"
for i in {1..60}; do
    timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo "$timestamp"
    cpu_temp=$(vcgencmd measure_temp | cut -d= -f2 | cut -d\' -f1)
    echo "$cpu_temp"
    cpu_clock_speed=$(($(vcgencmd measure_clock arm | awk -F= '{print $2}') / 1000000))
    echo "$cpu_clock_speed"
    throttled_status=$(vcgencmd get_throttled)
    echo "$throttled_status"
    echo "################"
    echo "$timestamp,$cpu_temp,$cpu_clock_speed,$throttled_status" >> "$output_file"

    # Sleep for 1 second
    sleep 1
done
stress --cpu 4 -t 300 &

echo "Stress data for 300 seconds"
for i in {1..300}; do
    timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo "$timestamp"
    cpu_temp=$(vcgencmd measure_temp | cut -d= -f2 | cut -d\' -f1)
    echo "$cpu_temp"
    cpu_clock_speed=$(($(vcgencmd measure_clock arm | awk -F= '{print $2}') / 1000000))
    echo "$cpu_clock_speed"
    throttled_status=$(vcgencmd get_throttled)
    echo "$throttled_status"
    echo "################"
    echo "$timestamp,$cpu_temp,$cpu_clock_speed,$throttled_status" >> "$output_file"

    # Sleep for 1 second
    sleep 1
done

echo "Stress test complete, 60 second cool down period"

echo "Cool down data for 60 seconds"
for i in {1..60}; do
    timestamp=$(date +"%Y-%m-%d %H:%M:%S")
    echo "$timestamp"
    cpu_temp=$(vcgencmd measure_temp | cut -d= -f2 | cut -d\' -f1)
    echo "$cpu_temp"
    cpu_clock_speed=$(($(vcgencmd measure_clock arm | awk -F= '{print $2}') / 1000000))
    echo "$cpu_clock_speed"
    throttled_status=$(vcgencmd get_throttled)
    echo "$throttled_status"
    echo "################"
    echo "$timestamp,$cpu_temp,$cpu_clock_speed,$throttled_status" >> "$output_file"

    # Sleep for 1 second
    sleep 1
done
Les Pounder

Les Pounder is an associate editor at Tom's Hardware. He is a creative technologist and for seven years has created projects to educate and inspire minds both young and old. He has worked with the Raspberry Pi Foundation to write and deliver their teacher training program "Picademy".

  • bit_user
    Thanks for publishing this. I had previously used some stuff in /sys/ to get info about the CPU clockspeed and temperature, which was fine for my purposes. It would've been very nice to see some explicit confirmation of when throttling happened, however.

    A few suggestions:
    The bash script is simple enough for the data collection, but analysis would benefit from Python, at which point I'd recommend using numpy.array to hold the data. It gives you a nice way to represent tabular data in a single data structure, and then select just the columns you're interested in.
    You can then use matplotlib to make nice plots.
    As for benchmarking, stress-ng is my go-to and I think a vastly deeper tool than stress. Try it with options: –cpu 4 –cpu-method matrixprodTo exercise the GPU, I think one command I've used is: glmark2-es2 –off-screen –run-forever (of course, you should first ensure you're using the actual GPU driver and not software emulation).Overall, thanks! I hope this means we can look forward to more detailed power & temperature data in future Pi benchmarks!
    ; )
    Reply
  • DotNetMaster777
    Good description of Vcgencmd !
    Reply
  • Spardorp
    I ran into issues that my Pi didnot know the vcgencmd.
    Then I found this https://www.nicm.dev/vcgencmd/So should anyone have the same issue, use that guide to install vcgencmd.
    Reply