0

I have written simple shell in C with job control and piping/redirection functionality. How can I compare execution time(real,user and sys) of this shell with BASH ? I tried to measure time of execution for e.g. ls command. Problem is that time of execution varies and for ls command (wall time) is ~0.002s - measured with BASH time built in function. How can I measure it for multiple executions? For example I measured it for multiple times of execution with simple BASH script:

 for i in {1..5000}
do
    ls
done

I don't know how to do something similar with my shell. I wrote for loop in code of my shell that parses and executes ls command 5000 times but probably for loop in bash script is much slower so it is not comparable.

3
  • Does your shell have a -c option or equivalent, a way to launch your shell and tell it to execute a command? Wouldn't it make more sense to use a program that takes a specific length of time to run when testing? Say a little C program that just waits for 2 seconds and exits. Then, run that in the different shells so any differences will be because of the shells. Is that an option?
    – terdon
    Commented May 1, 2023 at 17:57
  • I can execute it like ./shell ls. That makes more sense yes. Maybe I should use more complicated command lines with multiple pipes and redirections so the time to parse command line will more differ in bash and this shell. Commented May 1, 2023 at 18:47
  • 1
    It all depends on what you want to test, but I would certainly not test using anything that relies on reading the filesystem, since that would introduce confounding factors.
    – terdon
    Commented May 1, 2023 at 18:59

2 Answers 2

1

This will give you second granularity, which likely isn't enough, at least for ls.

for i in {1..5000}
do
    start=${SECONDS}
    ls
    end=${SECONDS}
    echo that took $((end - start)) seconds
done

You could use the date command to get nanoseconds since the epoch...

for i in {1..5000}
do
    start=$(date +%s%N)
    ls
    end=$(date +%s%N)
    echo that took $((end - start)) nanoseconds
done
3
  • … but the calling overhead and the variance of that would be much larger than nanoseconds, probably (for small directories) even than what it takes for ls to actually run. Commented May 1, 2023 at 19:11
  • 1
    Oh, for sure. Just trying to point the OP to a potential solution. Taking the timing before and after N executions then dividing by N, as suggested in another answer, may well be a more fruitful approach, and would, for large enough N, smooth out that overhead. Commented May 1, 2023 at 19:19
  • yep, and your approach seems good, just wanted to get the thought into OP's head that it might be slightly harder to measure these short timings. terdon's approach is not without problems – it does measure the duration it takes to first parse the "$com" string, then execute it. This might be very useful to someone writing a shell like OP, if they want to time the parsing effort, or it might be not so great, if they want to time the actual command, and have postponed writing a faster parser… Commented May 1, 2023 at 20:22
1

I am not entirely clear on exactly what you are trying to test, but the basic approach should indeed be running it X times, and then taking the average time. I have a little shell function I use to test answers I post here, which can probably be adapted to fit your needs. Take the basic logic of averaging and you should be able to play with it:

timethis () 
{ 
    max=$1;
    shift;
    for com in "$@";
    do
        printf 'COMMAND: %s\n' "$com";
        c=0;
        while [[ $c -lt $max ]]; do
            let c++;
            ( time -p eval "$com" ) 2>&1 | grep --color -oP 'real.*?\K[\d\.]+';
        done | awk -vm=$max '{k+=$1}END{print (k/m)}';
    done
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .