Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Feb 2005 14:59:24 +0100 (CET)
From:      Oliver Fromme <olli@lurza.secnetix.de>
To:        freebsd-current@FreeBSD.ORG
Subject:   Re: cynchronised sleep capbilty..
Message-ID:  <200502021359.j12DxO1X091658@lurza.secnetix.de>
In-Reply-To: <20050201101113.J572@localhost>

next in thread | previous in thread | raw e-mail | index | archive | help
Julian Elischer <julian@elischer.org> wrote:
 > I often find myself wanting to write shell scripts that do:
 > 
 > while :
 > do
 >         {report some statistic}
 >         sleep 10
 > done
 > 
 > 
 > now this is of course only approximate as the delay will not be
 > exactly 10 seconds and it will gradually creep..
 > 
 > This doesn't matter too much except that I now need to do
 > the same on 50 machines and I need the data to line up.

If a precision of 1 s is enough (i.e. the data will line up
with a distance of no more than 1 s), the following will work
fine:

INTERVAL=10     # in seconds!
while :; do
        NOW=`date +%s`
        sleep $(( ($NOW / $INTERVAL + 1 ) * $INTERVAL - $NOW ))
        report_results
done

It calls date(1) and sleep(1) once per 10 seconds, so the
overhead is low.

The following script snippet abuses sysctl kern.cp_time for
subsecond precision (stathz is usually 128, so the precision
is about 0.0078s).  It calls sysctl(8), bc(1) and sleep(1)
once per 10 seconds, so the overhead is still low.  This one
executes report_results exactly every 10 seconds, _but_
it's not synchronized when executed on multiple machines.

To get both sub-second precision and synchronization to
clocks across machines, an extension to sleep(1) would be
required, as you suggested.  I think it would also be nice
to be able to get milliseconds from date(1), although that
might be difficult to implement, because the strftime(3)
interface isn't able to provide such information.

Best regards
   Oliver



INTERVAL=10     # in seconds!

STATHZ=`sysctl -n kern.clockrate`
STATHZ=${STATHZ%?}
STATHZ=$(( ${STATHZ##*=} * `sysctl -n hw.ncpu` ))

MOD=$(( $INTERVAL * $STATHZ ))

StatCounter()
{
        set -- `sysctl -n kern.cp_time`
        echo $(( $1 + $2 + $3 + $4 + $5 ))
}

while :; do
        TICKS=$(( $MOD - `StatCounter` % $MOD ))
        sleep `echo "scale=6; $TICKS / $STATHZ" | bc`
        report_results
done



-- 
Oliver Fromme, secnetix GmbH & Co KG, Oettingenstr. 2, 80538 München
Any opinions expressed in this message may be personal to the author
and may not necessarily reflect the opinions of secnetix in any way.

"In My Egoistical Opinion, most people's C programs should be indented
six feet downward and covered with dirt."
        -- Blair P. Houghton



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200502021359.j12DxO1X091658>