Re: kqueue periodic timer confusion

2012-07-19 Thread Paul Albrecht
On Fri, 2012-07-13 at 07:22 -0500, Davide Italiano wrote:
 On Thu, Jul 12, 2012 at 5:25 PM, John Baldwin j...@freebsd.org wrote:
  On Thursday, July 12, 2012 11:08:47 am Davide Italiano wrote:
  On Thu, Jul 12, 2012 at 4:26 PM, John Baldwin j...@freebsd.org wrote:
   On Thursday, July 12, 2012 9:57:16 am Ian Lepore wrote:
   On Thu, 2012-07-12 at 08:34 -0400, John Baldwin wrote:
On Wednesday, July 11, 2012 5:00:47 pm Ian Lepore wrote:
 On Wed, 2012-07-11 at 14:52 -0500, Paul Albrecht wrote:
  Hi,
 
  Sorry about this repost but I'm confused about the responses I 
  received
  in my last post so I'm looking for some clarification.
 
  Specifically, I though I could use the kqueue timer as 
  essentially a
  drop in replacement for linuxfd_create/read, but was surprised 
  that
  the accuracy of the kqueue timer is much less than what I need 
  for my
  application.
 
  So my confusion at this point is whether this is consider to be a 
  bug or
  feature?
 
  Here's some test code if you want to verify the problem:
 
  #include stdio.h
  #include stdlib.h
  #include string.h
  #include unistd.h
  #include errno.h
  #include sys/types.h
  #include sys/event.h
  #include sys/time.h
 
  int
  main(void)
  {
  int i,msec;
  int kq,nev;
  struct kevent inqueue;
  struct kevent outqueue;
  struct timeval start,end;
 
  if ((kq = kqueue()) == -1) {
  fprintf(stderr, kqueue error!? errno = %s,
strerror(errno));
  exit(EXIT_FAILURE);
  }
  EV_SET(inqueue, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 
  20, 0);
 
  gettimeofday(start, 0);
  for (i = 0; i  50; i++) {
  if ((nev = kevent(kq, inqueue, 1, outqueue, 1, 
  NULL)) ==
-1) {
  fprintf(stderr, kevent error!? errno = 
  %s,
strerror(errno));
  exit(EXIT_FAILURE);
  } else if (outqueue.flags  EV_ERROR) {
  fprintf(stderr, EV_ERROR: %s\n,
strerror(outqueue.data));
  exit(EXIT_FAILURE);
  }
  }
  gettimeofday(end, 0);
 
  msec = ((end.tv_sec - start.tv_sec) * 1000) + (((100 +
end.tv_usec - start.tv_usec) / 1000) - 1000);
 
  printf(msec = %d\n, msec);
 
  close(kq);
  return EXIT_SUCCESS;
  }
 
 

 What you are seeing is just the way FreeBSD currently works.

 Sleeping (in most all of its various forms, and I've just looked at 
 the
 kevent code to verify this is true there) is handled by converting 
 the
 amount of time to sleep (usually specified in a timeval or timespec
 struct) to a count of timer ticks, using an internal routine called
 tvtohz() in kern/kern_time.c.  That routine rounds up by one tick to
 account for the current tick.  Whether that's a good idea or not (it
 probably was once, and probably not anymore) it's how things 
 currently
 work, and could explain the fairly consistant +1ms you're seeing.
   
This is all true, but mostly irrelevant for his case.  EVFILT_TIMER
installs a periodic callout that executes KNOTE() and then resets 
itself (via
callout_reset()) each time it runs.  This should generally be closer 
to
regulary spaced intervals than something that does:
   
  
   In what way is it irrelevant?  That is, what did I miss?  It appears to
   me that the next callout is scheduled by calling timertoticks() passing
   a count of milliseconds, that count is converted to a struct timeval and
   passed to tvtohz() which is where the +1 adjustment happens.  If you ask
   for 20ms and each tick is 1ms, then you'd get regular spacing of 21ms.
   There is some time, likely a small number of microseconds, that you've
   consumed of the current tick, and that's what the +1 in tvtohz() is
   supposed to account for according to the comments.
  
   The tvtohz() routine both rounds up in the usual way (value+tick-1)/tick
   and then adds one tick on top of that.  That seems not quite right to
   me, except that it is a way to g'tee that you don't return early, and
   that is the one promise made by sleep routines on any OS; those magical
   at least words always appear in the docs.
  
   Actually what I'm missing (that I know of) is how the scheduler works.
   Maybe the +1 adjustment to account for the fraction of the current tick
   you've already consumed is the right thing to do, even when that
   fraction is 1uS or less of a 1mS tick.  That would depend on scheduler
   behavior that I know nothing about.
  
   Oh.  My bad, sorry.  You are correct.  It is a bug to use +1

Re: kqueue periodic timer confusion

2012-07-12 Thread Paul Albrecht
On Thu, 2012-07-12 at 09:26 -0500, John Baldwin wrote:
 On Thursday, July 12, 2012 9:57:16 am Ian Lepore wrote:
  On Thu, 2012-07-12 at 08:34 -0400, John Baldwin wrote:
   On Wednesday, July 11, 2012 5:00:47 pm Ian Lepore wrote:
On Wed, 2012-07-11 at 14:52 -0500, Paul Albrecht wrote:
 Hi,
 
 Sorry about this repost but I'm confused about the responses I 
 received
 in my last post so I'm looking for some clarification.
 
 Specifically, I though I could use the kqueue timer as essentially a
 drop in replacement for linuxfd_create/read, but was surprised that
 the accuracy of the kqueue timer is much less than what I need for my
 application.
 
 So my confusion at this point is whether this is consider to be a bug 
 or
 feature?
 
 Here's some test code if you want to verify the problem:
 
 #include stdio.h
 #include stdlib.h
 #include string.h
 #include unistd.h
 #include errno.h
 #include sys/types.h
 #include sys/event.h
 #include sys/time.h
 
 int
 main(void)
 {
 int i,msec;
 int kq,nev;
 struct kevent inqueue;
 struct kevent outqueue;
 struct timeval start,end;
 
 if ((kq = kqueue()) == -1) {
 fprintf(stderr, kqueue error!? errno = %s, 
   strerror(errno));
 exit(EXIT_FAILURE);
 }
 EV_SET(inqueue, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 20, 
 0);
 
 gettimeofday(start, 0);
 for (i = 0; i  50; i++) {
 if ((nev = kevent(kq, inqueue, 1, outqueue, 1, 
 NULL)) == 
   -1) {
 fprintf(stderr, kevent error!? errno = %s, 
   strerror(errno));
 exit(EXIT_FAILURE);
 } else if (outqueue.flags  EV_ERROR) {
 fprintf(stderr, EV_ERROR: %s\n, 
   strerror(outqueue.data));
 exit(EXIT_FAILURE);
 }
 }
 gettimeofday(end, 0);
 
 msec = ((end.tv_sec - start.tv_sec) * 1000) + (((100 + 
   end.tv_usec - start.tv_usec) / 1000) - 1000);
 
 printf(msec = %d\n, msec);
 
 close(kq);
 return EXIT_SUCCESS;
 }
 
 

What you are seeing is just the way FreeBSD currently works.  

Sleeping (in most all of its various forms, and I've just looked at the
kevent code to verify this is true there) is handled by converting the
amount of time to sleep (usually specified in a timeval or timespec
struct) to a count of timer ticks, using an internal routine called
tvtohz() in kern/kern_time.c.  That routine rounds up by one tick to
account for the current tick.  Whether that's a good idea or not (it
probably was once, and probably not anymore) it's how things currently
work, and could explain the fairly consistant +1ms you're seeing.
   
   This is all true, but mostly irrelevant for his case.  EVFILT_TIMER
   installs a periodic callout that executes KNOTE() and then resets itself 
   (via 
   callout_reset()) each time it runs.  This should generally be closer to
   regulary spaced intervals than something that does:
   
  
  In what way is it irrelevant?  That is, what did I miss?  It appears to
  me that the next callout is scheduled by calling timertoticks() passing
  a count of milliseconds, that count is converted to a struct timeval and
  passed to tvtohz() which is where the +1 adjustment happens.  If you ask
  for 20ms and each tick is 1ms, then you'd get regular spacing of 21ms.
  There is some time, likely a small number of microseconds, that you've
  consumed of the current tick, and that's what the +1 in tvtohz() is
  supposed to account for according to the comments.
  
  The tvtohz() routine both rounds up in the usual way (value+tick-1)/tick
  and then adds one tick on top of that.  That seems not quite right to
  me, except that it is a way to g'tee that you don't return early, and
  that is the one promise made by sleep routines on any OS; those magical
  at least words always appear in the docs.
  
  Actually what I'm missing (that I know of) is how the scheduler works.
  Maybe the +1 adjustment to account for the fraction of the current tick
  you've already consumed is the right thing to do, even when that
  fraction is 1uS or less of a 1mS tick.  That would depend on scheduler
  behavior that I know nothing about.
 
 Oh.  My bad, sorry.  You are correct.  It is a bug to use +1 in this
 case.  That is, the +1 makes sense when you are computing a one-time delta
 for things like nanosleep().  It is incorrect when computing a periodic
 delta such as for computing the interval for an itimer (setitimer) or
 EVFILT_TIMER().
 
 Hah, setitimer()'s callout (realitexpire) uses tvtohz - 1:
 
 sys/kern/kern_time.c:
 
 /*
  * Real

Re: kqueue periodic timer confusion

2012-07-12 Thread Paul Albrecht
On Thu, 2012-07-12 at 10:40 -0500, Ian Lepore wrote:
 On Thu, 2012-07-12 at 17:08 +0200, Davide Italiano wrote:
  On Thu, Jul 12, 2012 at 4:26 PM, John Baldwin j...@freebsd.org wrote:
   On Thursday, July 12, 2012 9:57:16 am Ian Lepore wrote:
   On Thu, 2012-07-12 at 08:34 -0400, John Baldwin wrote:
On Wednesday, July 11, 2012 5:00:47 pm Ian Lepore wrote:
 On Wed, 2012-07-11 at 14:52 -0500, Paul Albrecht wrote:
  Hi,
 
  Sorry about this repost but I'm confused about the responses I 
  received
  in my last post so I'm looking for some clarification.
 
  Specifically, I though I could use the kqueue timer as essentially 
  a
  drop in replacement for linuxfd_create/read, but was surprised 
  that
  the accuracy of the kqueue timer is much less than what I need for 
  my
  application.
 
  So my confusion at this point is whether this is consider to be a 
  bug or
  feature?
 
  Here's some test code if you want to verify the problem:
 
  #include stdio.h
  #include stdlib.h
  #include string.h
  #include unistd.h
  #include errno.h
  #include sys/types.h
  #include sys/event.h
  #include sys/time.h
 
  int
  main(void)
  {
  int i,msec;
  int kq,nev;
  struct kevent inqueue;
  struct kevent outqueue;
  struct timeval start,end;
 
  if ((kq = kqueue()) == -1) {
  fprintf(stderr, kqueue error!? errno = %s,
strerror(errno));
  exit(EXIT_FAILURE);
  }
  EV_SET(inqueue, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 
  20, 0);
 
  gettimeofday(start, 0);
  for (i = 0; i  50; i++) {
  if ((nev = kevent(kq, inqueue, 1, outqueue, 1, 
  NULL)) ==
-1) {
  fprintf(stderr, kevent error!? errno = 
  %s,
strerror(errno));
  exit(EXIT_FAILURE);
  } else if (outqueue.flags  EV_ERROR) {
  fprintf(stderr, EV_ERROR: %s\n,
strerror(outqueue.data));
  exit(EXIT_FAILURE);
  }
  }
  gettimeofday(end, 0);
 
  msec = ((end.tv_sec - start.tv_sec) * 1000) + (((100 +
end.tv_usec - start.tv_usec) / 1000) - 1000);
 
  printf(msec = %d\n, msec);
 
  close(kq);
  return EXIT_SUCCESS;
  }
 
 

 What you are seeing is just the way FreeBSD currently works.

 Sleeping (in most all of its various forms, and I've just looked at 
 the
 kevent code to verify this is true there) is handled by converting 
 the
 amount of time to sleep (usually specified in a timeval or timespec
 struct) to a count of timer ticks, using an internal routine called
 tvtohz() in kern/kern_time.c.  That routine rounds up by one tick to
 account for the current tick.  Whether that's a good idea or not (it
 probably was once, and probably not anymore) it's how things 
 currently
 work, and could explain the fairly consistant +1ms you're seeing.
   
This is all true, but mostly irrelevant for his case.  EVFILT_TIMER
installs a periodic callout that executes KNOTE() and then resets 
itself (via
callout_reset()) each time it runs.  This should generally be closer to
regulary spaced intervals than something that does:
   
  
   In what way is it irrelevant?  That is, what did I miss?  It appears to
   me that the next callout is scheduled by calling timertoticks() passing
   a count of milliseconds, that count is converted to a struct timeval and
   passed to tvtohz() which is where the +1 adjustment happens.  If you ask
   for 20ms and each tick is 1ms, then you'd get regular spacing of 21ms.
   There is some time, likely a small number of microseconds, that you've
   consumed of the current tick, and that's what the +1 in tvtohz() is
   supposed to account for according to the comments.
  
   The tvtohz() routine both rounds up in the usual way (value+tick-1)/tick
   and then adds one tick on top of that.  That seems not quite right to
   me, except that it is a way to g'tee that you don't return early, and
   that is the one promise made by sleep routines on any OS; those magical
   at least words always appear in the docs.
  
   Actually what I'm missing (that I know of) is how the scheduler works.
   Maybe the +1 adjustment to account for the fraction of the current tick
   you've already consumed is the right thing to do, even when that
   fraction is 1uS or less of a 1mS tick.  That would depend on scheduler
   behavior that I know nothing about.
  
   Oh.  My bad, sorry.  You are correct.  It is a bug to use +1 in this
   case.  That is, the +1 makes sense when you are computing a one-time delta

Re: kqueue timer timeout period

2012-07-11 Thread Paul Albrecht
On Wed, 2012-07-11 at 03:36 -0500, Harti Brandt wrote:
 On Wed, 11 Jul 2012, Peter Jeremy wrote:
 
 PJOn 2012-Jul-10 10:03:08 -0500, Paul Albrecht albre...@glccom.com wrote:
 PJI have a question about the kqueue timer timeout period ... what's data
 PJsupposed to be? I thought it was supposed to be the period in
 PJmilliseconds, but I seem to off by one.
 PJ
 PJFor example, if I set date (the timeout period) to 20 milliseconds, I
 PJoften wait 21 milliseconds which is very undesirable for my application.
 PJ
 PJFreeBSD is not a real-time OS.  The timeouts specified in various
 PJsyscalls (eg kevent(EVFILT_TIMER), nanosleep(), select(), poll())
 PJspecify minimum timeouts.  Once the timeout (rounded up to the next
 PJtick) has expired, the process will be placed back into the queue
 PJof processes eligible to be run by the scheduler - which may impose
 PJa further arbitrary delay.
 PJ
 PJPeriodic timers are somewhat better behaved:  Scheduler delays only
 PJimpact process scheduling after the timeout expires and the average
 PJrate should be very close to that requested.
 
 While it is certainly true that FreeBSD is not a real-time OS, this does 
 not explain the timer problems. 2 or 3 month ago I did a simple test with 
 select and poll: I observed a systematic error of about 3-5% of the 
 waiting time. So when you wait for 20ms, you may get 21ms (if running with 
 a low HZ value) because of rounding. But if you wait for 100s, you get 103 
 or even 105s on a completly idle machine (all services disabled).
 
 I think that this is not a problem with beeing non-realtime, but a problem 
 with time-keeping. Shouldn't it be possible to do this better?
 

I don't think it has anything to do with realtime either. I've been
using gentoo linux to run my application using timerfd_create/read for
20 millisecond timing without any problems.

 harti
-- 
Paul Albrecht

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: [[SPAM]] Re: kqueue timer timeout period

2012-07-11 Thread Paul Albrecht
On Wed, 2012-07-11 at 04:42 -0500, Alexander Motin wrote:
 Hi.
 
 Historically FreeBSD used completely different hardware time sources for 
 time keeping and time events. Not sure about 5%, but the last could be 
 less precise in some cases. FreeBSD 9.0, depending on hardware, can be 
 more precise because of using same time source in both cases. Also there 
 is ongoing GSoC project now by Davide Italiano to handle sub-HZ 
 resolution for time events. Present tests show reaching 20 microseconds 
 precision; and I think it can be improved further.
 

I'm definitely not getting getting 20 millisecond timing with freebsd
kqueue which surprised me because I get it with linux
linuxfd_create/read using the same hardware.

-- 
Paul Albrecht

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


kqueue periodic timer confusion

2012-07-11 Thread Paul Albrecht

Hi,

Sorry about this repost but I'm confused about the responses I received
in my last post so I'm looking for some clarification.

Specifically, I though I could use the kqueue timer as essentially a
drop in replacement for linuxfd_create/read, but was surprised that
the accuracy of the kqueue timer is much less than what I need for my
application.

So my confusion at this point is whether this is consider to be a bug or
feature?

Here's some test code if you want to verify the problem:

#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include errno.h
#include sys/types.h
#include sys/event.h
#include sys/time.h

int
main(void)
{
int i,msec;
int kq,nev;
struct kevent inqueue;
struct kevent outqueue;
struct timeval start,end;

if ((kq = kqueue()) == -1) {
fprintf(stderr, kqueue error!? errno = %s, strerror(errno));
exit(EXIT_FAILURE);
}
EV_SET(inqueue, 1, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 20, 0);

gettimeofday(start, 0);
for (i = 0; i  50; i++) {
if ((nev = kevent(kq, inqueue, 1, outqueue, 1, NULL)) == -1) {
fprintf(stderr, kevent error!? errno = %s, 
strerror(errno));
exit(EXIT_FAILURE);
} else if (outqueue.flags  EV_ERROR) {
fprintf(stderr, EV_ERROR: %s\n, 
strerror(outqueue.data));
exit(EXIT_FAILURE);
}
}
gettimeofday(end, 0);

msec = ((end.tv_sec - start.tv_sec) * 1000) + (((100 + end.tv_usec 
- start.tv_usec) / 1000) - 1000);

printf(msec = %d\n, msec);

close(kq);
return EXIT_SUCCESS;
}


-- 
Paul Albrecht

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


kqueue timer timeout period

2012-07-10 Thread Paul Albrecht

Hi,

I have a question about the kqueue timer timeout period ... what's data
supposed to be? I thought it was supposed to be the period in
milliseconds, but I seem to off by one.

For example, if I set date (the timeout period) to 20 milliseconds, I
often wait 21 milliseconds which is very undesirable for my application.

-- 
Paul Albrecht

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org