Re: kqueue periodic timer confusion
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
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
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
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
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
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
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