You could make use of the
/proc filesystem, which will be lightning fast. You can do something like this:
# for PROC in $(ls /proc/ | grep -E '[0-9]') ; do echo "$(ls /proc/"$PROC"/fd/ | wc -l) FD for PID $PROC ($(ps -p $PROC -o comm=))" ; done | sort -g | tail -3
On my current machine I get these results:
ls: cannot access '/proc/25710/fd/': No such file or directory
ls: cannot access '/proc/25711/fd/': No such file or directory
ls: cannot access '/proc/25712/fd/': No such file or directory
126 FD for PID 289 (systemd-journal)
170 FD for PID 3203 (firefox)
185 FD for PID 1 (systemd)
It should throw some errors, since processes appear and end while the data goes through the iteration and the pipes, but after some testing on various systems the slowest run was 3s. You’ll need to run it as
root to be able to access file descriptors of all processes.
The above command displays the top 3 process, you can adjust it by modifying the argument of the last
tail. For example, if you need the top 10, you can change the last part to
tail -10. If you need a full listing of every process, you can omit the
| tail -3 part altogether.