Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance profiling tools for shell scripts

I'm attempting to speed up a collection of scripts that invoke subshells and do all sorts of things. I was wonder if there are any tools available to time the execution of a shell script and its nested shells and report on which parts of the script are the most expensive.

For example, if I had a script like the following.

#!/bin/bash  echo "hello" echo $(date) echo "goodbye" 

I would like to know how long each of the three lines took. time will only only give me total time for the script. bash -x is interesting but does not include timestamps or other timing information.

like image 894
bradtgmurray Avatar asked Dec 02 '10 14:12

bradtgmurray


People also ask

Which software is used for shell script?

Bash: Bash is a UNIX shell and command language written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell.

What is GT in shell?

-gt means "greater than". It is used to compare integers for the inequality that is usually written > in other languages (in some shells, with the test utility or inside [ ... ] , > compares two strings for lexicographical ordering, so it has a very different meaning from -gt ).

What is PID in shell script?

A process is given a unique number called process ID (PID) that identifies that process to the system, when it is started. If we ever need to kill a process, for an example, we can refer to it by its PID.


1 Answers

You can set PS4 to show the time and line number. Doing this doesn't require installing any utilities and works without redirecting stderr to stdout.

For this script:

#!/bin/bash -x # Note the -x flag above, it is required for this to work PS4='+ $(date "+%s.%N ($LINENO) ")' for i in {0..2} do     echo $i done sleep 1 echo done 

The output looks like:

+ PS4='+ $(date "+%s.%N ($LINENO) ")' + 1291311776.108610290 (3) for i in '{0..2}' + 1291311776.120680354 (5) echo 0 0 + 1291311776.133917546 (3) for i in '{0..2}' + 1291311776.146386339 (5) echo 1 1 + 1291311776.158646585 (3) for i in '{0..2}' + 1291311776.171003138 (5) echo 2 2 + 1291311776.183450114 (7) sleep 1 + 1291311777.203053652 (8) echo done done 

This assumes GNU date, but you can change the output specification to anything you like or whatever matches the version of date that you use.

Note: If you have an existing script that you want to do this with without modifying it, you can do this:

PS4='+ $(date "+%s.%N ($LINENO) ")' bash -x scriptname 

In the upcoming Bash 5, you will be able to save forking date (but you get microseconds instead of nanoseconds):

PS4='+ $EPOCHREALTIME ($LINENO) ' 
like image 96
Dennis Williamson Avatar answered Sep 19 '22 01:09

Dennis Williamson