I'm working on a system on which ubuntu is running. I'm reading basic data like CPU frequency and temperature out of the thermal zones provided in /sys/class/thermal.
Unfortunately, I've got around 100 thermal_zones from which I need to read the data. I do it with:
for SENSOR_NODE in /sys/class/thermal/thermal_zone*; do printf "%s: %s\n" $(cat ${SENSOR_NODE}/type) $(cat ${SENSOR_NODE}/temp); done
To collect all data takes ~2.5-3 sec. which is way to long. Since I want to collect the data every second my question is, if there is a way to "read" or "collect" the data faster?
Thank you in advance
CodePudding user response:
There's only so much you can do while writing your code in shell, but let's start with the basics.
- Command substitutions,
$(...)
, are expensive: They require creating a FIFO,fork()
ing a new subprocess, connecting the FIFO to that subprocess's stdout, reading from the FIFO and waiting for the commands running in that subshell to exit. - External commands, like
cat
, are expensive: They require linking and loading a separate executable; and when you run them withoutexec
(in which case they inherit and consume the shell's process ID), they also require a new process to befork()
ed off.
All POSIX-compliant shells give you a read
command:
for sensor_node in /sys/class/thermal/thermal_zone*; do
read -r sensor_type <"$sensor_node/type" || continue
read -r sensor_temp <"$sensor_node/temp" || continue
printf '%s: %s\n' "$sensor_type" "$sensor_temp"
done
...which lets you avoid the command substitution overhead and the overhead of cat
. However, read
reads content only one byte at a time; so while you're not paying that overhead, it's still relatively slow.
If you switch from /bin/sh
to bash
, you get a faster alternative:
for sensor_node in /sys/class/thermal/thermal_zone*; do
printf '%s: %s\n' "$(<"$sensor_node/type)" "$(<sensor_node/temp)"
done
...as $(<file)
doesn't need to do the one-byte-at-a-time reads that read
does. That's only faster for being bash, though; it doesn't mean it's actually fast. There's a reason modern production monitoring systems are typically written in Go or with a JavaScript runtime like Node.