Does ZSH's time command take any arguments like -p? - performance

I recently installed the developer beta of macOS 10.15 Catalina, which defaults to ZSH instead of BASH.
I have time installed as a binary in /usr/bin/time, and use that to time some of my scripts. ZSH, however, has this as a built-in command. My problem is that I usually use time -p to format its output in a way I prefer, but that doesn't seem to be possible on ZSH.
According to man time:
-p The output is formatted as specified by IEEE Std 1003.2-1992 (``POSIX.2'').
This doesn't seem to apply to ZSH's built-in, and ZSH doesn't seem to be using my installed time binary:
BASH
bash-5.0$ which time
/usr/bin/time
bash-5.0$ time echo hello; echo $?
hello
real 0m0.000s
user 0m0.000s
sys 0m0.000s
0
bash-5.0$ time -p echo hello; echo $?
hello
real 0.00
user 0.00
sys 0.00
0
ZSH
is-mbp-bleggiero% which time
time: shell reserved word
is-mbp-bleggiero% time echo hello; echo $?
hello
0
is-mbp-bleggiero% time -p echo hello; echo $?
zsh: command not found: -p
-p echo hello 0.00s user 0.00s system 74% cpu 0.001 total
127
And that looks odd to me; it seems to be including the info I want (user vs system & total, formatted as seconds), but it also doesn't run the command, instead complaining that it doesn't exist.

You can call /usr/bin/time -p if you want to use this option, or =time -p
The zsh builtin time doesn't take any option (man zshmisc).
But you can export TIMEFMT with the format you want, including newlines with \n.
echo $TIMEFMT to see what it is now

Related

bash 30 second delay when checking if file exists

I have a file system that is shared between several computers. I cannot open network connections between these computers so I have written a program to communicate via files. I have a server that checks a folder for the appearance of instruction files, it reads, executes and writes an output file and then creates a signal file to indicate the file is ready.
to check for a file with a while loop
while [[ ! -e $READY_FILE ]]
do sleep 1
done
do something
The server gets and processes the file pretty much right away and makes the signal file but I am seeing a strange latency on the client side.
when the server and client are running on the same machine the latency is very low. When I run the client on a separate computer the latency is around 30 seconds.
time bash client.sh -f commands.txt
done
real 0m31.945s
user 0m0.048s
sys 0m0.314s
This is reproducible +/- 2 seconds.
I can kill the problem by making the client computer do anything with the working directory.
time bash client.sh -f commands.txt & sleep 5; ls $wd >/dev/null
real 0m5.120s
user 0m0.014s
sys 0m0.083s
time bash client.sh -f commands.txt & sleep 3.5; ls $wd >/dev/null
real 0m3.749s
user 0m0.011s
sys 0m0.055s
I can correct it in the program by changing the while loop to
while [[ ! -e $READY_FILE ]]
do ls $wd >/dev/null
sleep 1
done
Now i get
time bash client.sh -f commands.txt
real 0m1.075s
user 0m0.004s
sys 0m0.056s
My question is why is there a 30 second delay for the test [[ -e $READY_FILE ]] to detect the file?

Why zsh time not work for some commands but bash time could?

Why Zsh time not work for some commands,
➜ ~ type time
time is a reserved word
➜ ~ time sleep 1
sleep 1 0.00s user 0.00s system 0% cpu 1.004 total
# not work for echo
➜ ~ time echo hello
hello
# not work with for
➜ ~ time for i in {1..3}; do curl -s http://baidu.com > /dev/null; done
but if change to bash these commends are both supported,
➜ ~ exec bash
bash-3.2$ type time
time is a shell keyword
$ time echo hello
hello
real 0m0.000s
user 0m0.000s
sys 0m0.000s
bash-3.2$ time for i in {1..3}; do curl -s http://baidu.com > /dev/null; done
real 0m0.099s
user 0m0.019s
sys 0m0.018s

/usr/bin/time giving its output in one single line

I may have a locale problem or something similar, because whenever I run /usr/bin/time it gives me the output as a single line, difficult to interpret :
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 1756maxresident)k
The above comes from echo with no parameters, but it's the case with all commands.
try to use the 'POSIX' style:
$ /usr/bin/time -p ls
or integrated time in bash/zsh/fish...
$ time ls
or use your style, by creating a var called TIME or in some system called TIMEFORMAT
$ export TIME="%E"
$ /usr/bin/time ls

How to obtain the time statistics with jar program? [duplicate]

Just a little question about timing programs on Linux: the time command allows to
measure the execution time of a program:
[ed#lbox200 ~]$ time sleep 1
real 0m1.004s
user 0m0.000s
sys 0m0.004s
Which works fine. But if I try to redirect the output to a file, it fails.
[ed#lbox200 ~]$ time sleep 1 > time.txt
real 0m1.004s
user 0m0.001s
sys 0m0.004s
[ed#lbox200 ~]$ cat time.txt
[ed#lbox200 ~]$
I know there are other implementations of time with the option -o to write a file but
my question is about the command without those options.
Any suggestions ?
Try
{ time sleep 1 ; } 2> time.txt
which combines the STDERR of "time" and your command into time.txt
Or use
{ time sleep 1 2> sleep.stderr ; } 2> time.txt
which puts STDERR from "sleep" into the file "sleep.stderr" and only STDERR from "time" goes into "time.txt"
Simple. The GNU time utility has an option for that.
But you have to ensure that you are not using your shell's builtin time command, at least the bash builtin does not provide that option! That's why you need to give the full path of the time utility:
/usr/bin/time -o time.txt sleep 1
Wrap time and the command you are timing in a set of brackets.
For example, the following times ls and writes the result of ls and the results of the timing into outfile:
$ (time ls) > outfile 2>&1
Or, if you'd like to separate the output of the command from the captured output from time:
$ (time ls) > ls_results 2> time_results
If you care about the command's error output you can separate them like this while still using the built-in time command.
{ time your_command 2> command.err ; } 2> time.log
or
{ time your_command 2>1 ; } 2> time.log
As you see the command's errors go to a file (since stderr is used for time).
Unfortunately you can't send it to another handle (like 3>&2) since that will not exist anymore outside the {...}
That said, if you can use GNU time, just do what #Tim Ludwinski said.
\time -o time.log command
Since the output of 'time' command is error output, redirect it as standard output would be more intuitive to do further processing.
{ time sleep 1; } 2>&1 | cat > time.txt
If you are using GNU time instead of the bash built-in, try
time -o outfile command
(Note: GNU time formats a little differently than the bash built-in).
&>out time command >/dev/null
in your case
&>out time sleep 1 >/dev/null
then
cat out
I ended up using:
/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
Where "a" is append
Where "o" is proceeded by the file name to append to
Where "f" is format with a printf-like syntax
Where "%E" produces 0:00:00; hours:minutes:seconds
I had to invoke /usr/bin/time because the bash "time" was trampling it and doesn't have the same options
I was just trying to get output to file, not the same thing as OP
If you don't want to touch the original process' stdout and stderr, you can redirect stderr to file descriptor 3 and back:
$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out
real 0m0.009s
user 0m0.004s
sys 0m0.000s
You could use that for a wrapper (e.g. for cronjobs) to monitor runtimes:
#!/bin/bash
echo "[$(date)]" "$#" >> /my/runtime.log
{ time { "$#" 2>&3; }; } 3>&2 2>> /my/runtime.log
#!/bin/bash
set -e
_onexit() {
[[ $TMPD ]] && rm -rf "$TMPD"
}
TMPD="$(mktemp -d)"
trap _onexit EXIT
_time_2() {
"$#" 2>&3
}
_time_1() {
time _time_2 "$#"
}
_time() {
declare time_label="$1"
shift
exec 3>&2
_time_1 "$#" 2>"$TMPD/timing.$time_label"
echo "time[$time_label]"
cat "$TMPD/timing.$time_label"
}
_time a _do_something
_time b _do_another_thing
_time c _finish_up
This has the benefit of not spawning sub shells, and the final pipeline has it's stderr restored to the real stderr.
If you are using csh you can use:
/usr/bin/time --output=outfile -p $SHELL -c 'your command'
For example:
/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
If you want just the time in a shell variable then this works:
var=`{ time <command> ; } 2>&1 1>/dev/null`

time command don't let me use -f with bash functions

I'd like to use time command in a bash script to calculate the elapsed time of some function, but time command gives me error messages when I try to call it to measure one of the script's functions using any of its options, like '--format', which I want to make use of.
The same thing happens if I use 'time [...]' from terminal, with any command. However, using it from terminal, it works when I enter '/usr/bin/time [...]' instead of just 'time [...]', but when I call '/usr/bin/time ANY_FUNCTION_INSIDE_ANY_SCRIPT [arguments]' in a script, it complains about the called function being not a valid command.
test.sh code:
#!/bin/bash
testime ()
{
printf "test message is \"$1\" \n"
printf "just testing...\n"
sleep 5
read -p "enter something: " buffer
echo $buffer
}
time -f "testime() finished after %E" testime "damn!"
printf "Bye bye!\n\n"
exit
Output:
$ ./test.sh
./test.sh: line 12: -f: command not found
real 0m0.001s
user 0m0.000s
sys 0m0.001s
Bye bye!
BUT... If i use time without options, like "-f ...", as here:
[...]
time testime "damn!"
printf "Bye bye!\n\n"
exit
...the script works correctly, as you can see:
$ ./test.sh
test message is "damn!"
just testing...
enter something: SOMETHING_I_HAVE_ENTERED
SOMETHING_I_HAVE_ENTERED
real 0m24.050s
user 0m0.000s
sys 0m0.001s
Bye bye!
AND when I call '/usr/bin/time -f [...]', as it would work when I'm doing stuff from terminal, using '-f [...]' or not, it gives me some output like this:
$ ./test.sh
/usr/bin/time: cannot run testime: No such file or directory
Command exited with non-zero status 127
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 340maxresident)k
0inputs+0outputs (0major+72minor)pagefaults 0swaps
Bye bye!
Does someone know why it happens?
Mention the command and -f option at the end.
Shell> time testime 'damn!' -f 'testime() finished after %E'
test message is "damn!"
just testing...
enter something: abc
abc
real 0m7.513s
user 0m0.000s
sys 0m0.003s
The usage of the test command clearly mentioned that you need to give command before to options.
NAME
time - time a simple command or give resource usage
SYNOPSIS
time [options] command [arguments...]
In [options] only -P is given and remaining are arguments.

Resources