Home > Mobile >  Linux - read or collect file content faster (e.g. cpu temp every sec.)
Linux - read or collect file content faster (e.g. cpu temp every sec.)

Time:06-19

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 without exec (in which case they inherit and consume the shell's process ID), they also require a new process to be fork()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.

  • Related