11

I'm building my own android rom. In order to build it, I need to run

mka -j8 bacon

However, I wanted to measure the time it took to build it, so I used

/usr/bin/time -f "User\t%U\nSys\t%S\nReal\t%E\nCPU\t%P" mka -j8 bacon

This won't run, because it's saying

/usr/bin/time: cannot run mka: No such file or directory

Any help how to work around this, it's appreciated! I'm running xubuntu.

Edit:

For some reason, using make instead of mka does work, however using mka is better.

/usr/bin/time -f "User\t%U\nSys\t%S\nReal\t%E\nCPU\t%P" make -j8 bacon

Edit 2: from the cyanogenmod website

Invoking $ source build/envsetup.sh or $ . build/envsetup.sh from your shell runs the envsetup.sh script in the build directory. envsetup.sh adds many functions to the build environment, the most important of which are listed below.

source build/evnsetup.sh is the command I run before executing time. One of those added functions by evnsetup.sh is mka, is it possible to call this from within the time command?

Edit 3: Output of type mka

$ type mka
mka is a function
mka () 
{ 
    case `uname -s` in 
        Darwin)
            make -j `sysctl hw.ncpu|cut -d" " -f2` "$@"
        ;;
        *)
            schedtool -B -n 1 -e ionice -n 1 make -j$(cat /proc/cpuinfo | grep "^processor" | wc -l) "$@"
        ;;
    esac
}
muru
  • 193,181
  • 53
  • 473
  • 722
P1nGu1n
  • 213
  • 1
  • 2
  • 7
  • Have you tried to put the entire path of mka (something like /usr/bin/mka )? – desgua Mar 07 '14 at 16:58
  • The problem is is that evnsetup.sh initializes some stuff. In the terminal I have to execute that file before I'm able to call mka. Apparently it's not recognized when calling it as a parameter from the time command. – P1nGu1n Mar 07 '14 at 17:00
  • How can I reproduce this? – Braiam Mar 07 '14 at 22:39
  • After you executed your `source build/evnsetup.sh`, at the point where you want to call `time mka -j8 bacon`, can you post the output of the command `type mka`? – Malte Skoruppa Mar 08 '14 at 04:42
  • @MalteSkoruppa output added, mka appears to be a bash function? – P1nGu1n Mar 10 '14 at 19:23

1 Answers1

11

The problem is that mka is a bash function exported by your script and not an executable (as opposed to make), so /usr/bin/time doesn't find it, as it looks for an executable.

There are two possible solutions.

First, note that there is a difference between the bash built-in function time, and the executable /usr/bin/time. These are different commands, which take different parameters and generate different output:

$ time sleep 1

real    0m1.001s
user    0m0.000s
sys     0m0.001s

$ /usr/bin/time sleep 1
0.00user 0.00system 0:01.00elapsed 0%CPU (0avgtext+0avgdata 664maxresident)k
0inputs+0outputs (0major+215minor)pagefaults 0swaps

Type help time to get help for the bash built-in time. Type man time to get help for the executable /usr/bin/time.

The first solution uses time, whereas the second solution uses /usr/bin/time.

First solution: using the bash built-in function time

The bash built-in function time is aware of declared bash functions, and you can immediately use it to measure the time of such functions.

$ foo() {
    sleep 1;
    echo "Hello World"
  }
$ time foo
Hello World

real    0m1.002s
user    0m0.000s
sys     0m0.001s

In your case, the following command should work:

$ time mka -j8 bacon

This would be my preferred way. However, it may not generate exactly the output you want. In particular, it does not measure or print CPU usage.

Second solution: using the executable /usr/bin/time

You cannot directly measure the time of a built-in bash function using /usr/bin/time (as far as I know), but what you can do is measure the time of the /bin/bash executable executing that bash function. This is a little hacky, and it generates a little overhead as you are launching an extra instance of bash. But this overhead may be negligible when faced with a function that takes minutes to compute, so it may still suit your needs better.

To be able to launch the /bin/bash executable on a bash function, we have to export the function first.

$ foo() {
    sleep 1;
    echo "Hello World"
  }
$ export -f foo
$ echo foo | /usr/bin/time /bin/bash
Hello World
0.00user 0.00system 0:01.00elapsed 0%CPU (0avgtext+0avgdata 1476maxresident)k
0inputs+0outputs (0major+707minor)pagefaults 0swaps

Hence, in your case, to be able to use /usr/bin/time and generate the output format you want, you could proceed as follows:

$ export -f mka
$ echo 'mka -j8 bacon' | /usr/bin/time -f "User\t%U\nSys\t%S\nReal\t%E\nCPU\t%P" /bin/bash
Malte Skoruppa
  • 12,856
  • 5
  • 56
  • 65
  • Thank you, I really understand why it wasn't working! Two short questions, what does the `-f` parameter, I wasn't able to find this. Second, what does /bin/bash? Really appreciate it! – P1nGu1n Mar 10 '14 at 19:32
  • 1
    The `-f` parameter to `export` tells `export` to export a shell function. See `help export`. The `-f` parameter to `/usr/bin/time` tells `/usr/bin/time` to expect a format string, but I assume this you know. The `/bin/bash` part of the last command is the bash executable whose execution time is actually measured, when it itself executes the exported `mka` function. It executes the `mka` function because it reads and executes the `mka -j8 bacon` command from standard input, which is why we use `echo` and a pipe. Sorry for the late answer, just read this. :) – Malte Skoruppa Jun 05 '14 at 22:06