Re: How do get elapsed time in milliseconds in a shell script?
- In reply to: Steve O'Hara-Smith : "Re: How do get elapsed time in milliseconds in a shell script?"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 20 Jul 2022 15:35:42 UTC
On 19 July 2022 12:42:27 am AEST, Steve O'Hara-Smith <steve@sohara.org> wrote:
> On Mon, 18 Jul 2022 14:01:01 +0100
> freebsd-doc@fjl.co.uk wrote:
>
> > I think what may be needed is a base utility to produce the
> accurate
> > tick since the epoch or boot - it doesn't' matter for timeing.
> Possibly
> > an extension to "uptime", which I assume must know.
>
> There are some counters exposed via sysctl which might be useful,
> kern.timecounter.tc.HPET.counter looks promising, the rest seem to
> cycle
> rather quickly. Of course portability is an issue with using these.
I must admit to being puzzled as to the efficacy of looking for millisecond precision for event timing or uptime on a non-realtime OS, when there are so many things that bend time going on. Sure, the kernel has a pretty good idea of what's what and when's when, but out here in userland it's pretty fluid.
One's system may have a good lock to network time, at boot anyway, but once we're talking about something that can be called up in a script, anything past 100ms is slippery.
In concord about HPET being the likely best timecounter for this, if it's also on non-Intel systems? So I've had a bit of a play in the script below. HPET wraps at ~300 seconds, so anything longer term has to be driven by interrupts off that. We have kernel hackers for that ...
Anyway, I think running this should illustrate, if nothing else, the vagaries of userland timesharing especially in scripts. This tested on 12.3-RELEASE, 2.6GHz i5 3320M, otherwise idle.
Also, csh's time command already reports millisecond system and user times, with decisecond elapsed time for process timing; it's in base; and can be invoked from sh by such as
$ csh -c 'time sh -c "${myscript}"'
cheers, Ian
* tabs may not survive pasting
<code>
#!/bin/sh
# kern.timecounter.tc.HPET.frequency: 14318180 period: 69.841ns
# kern.timecounter.tc.HPET.mask: 4294967295 repeat: 299.966s
period=69.841 # ns
[ "$1" ] && j="$1" || j=25
j=$((j+1))
for i in `jot - 1 $j`; do
this=`sysctl -n kern.timecounter.tc.HPET.counter`
if [ $i -eq 1 ]; then
echo "this prev step msec"
else
step=`echo "scale=12; $this - $prev" | bc`
msec=`echo "scale=3; $step * $period / 10^6" | bc`
echo "$this $prev $step $msec"
fi
prev=$this
done
exit 0
</code>