Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Linux – read or collect file content faster (e.g. cpu temp every sec.)

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Thank you in advance

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading