On Fri, May 28, 2021 at 08:15:20AM +0200, Mark Kettenis wrote: > > Date: Thu, 27 May 2021 18:29:04 -0500 > > From: Scott Cheloha <scottchel...@gmail.com> > > Sorry, but does is one of those areas where I'm not very aware how the > interfaces are used by applications. So my default position is: > "don't change it". Especially since these are "legacy" interfaces. > > > On Wed, May 19, 2021 at 10:32:55AM -0500, Scott Cheloha wrote: > > > On Wed, May 12, 2021 at 01:15:05PM -0500, Scott Cheloha wrote: > > > > > > > > [...] > > > > > > > > Paul de Weerd mentioned off-list that the initial expiration for an > > > > ITIMER_REAL timer is always at least one tick. I looked into it and > > > > yes, this is the case, because the kernel rounds it_value up to one > > > > tick if it is non-zero. > > > > > > > > After thinking about it a bit I don't think we should do this > > > > rounding. At least, not for the initial expiration. > > The manual page explicity says: > > "Time values smaller than the resolution of the system clock are > rounded up to this reolution (typically 10 milliseconds)". > > which has been there from revision 1. > > Note that POSIX defines timer_gettime() and timer_settime(), which we > don't implement. We don't implement these, but the POSIX standard > says in the rationale: > > "Practical clocks tick at a finite rate, with rates of 100 hertz and > 1000 hertz being common. The inverse of this tick rate is the > clock resolution, also called the clock granularity, which in > either case is expressed as a time duration, being 10 milliseconds > and 1 millisecond respectively for these common rates. The > granularity of practical clocks implies that if one reads a given > clock twice in rapid succession, one may get the same time value > twice; and that timers must wait for the next clock tick after the > theoretical expiration time, to ensure that a timer never returns > too soon. Note also that the granularity of the clock may be > significantly coarser than the resolution of the data format used > to set and get time and interval values. Also note that some > implementations may choose to adjust time and/or interval values to > exactly match the ticks of the underlying clock." > > which seems to imply that rounding up is what is desired here as well, > although I presume here the actual resolution of the clock is supposed > to be used. But for timers associated with the > CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID that would be > realstathz, which is still tick-like... > > In other words, I'm not convinced... >
I adjusted Paul de Weerds timer.c code to work with all three setitimer clocks. The result is this: Before: ITIMER_REAL timeout 800000us min/avg/max/std-dev: 800208/808854.500/811085/3043.725 us timeout 400000us min/avg/max/std-dev: 400210/409098.031/410645/2786.929 us timeout 200000us min/avg/max/std-dev: 200035/209098.641/212912/2759.900 us timeout 100000us min/avg/max/std-dev: 100025/108900.367/110360/3057.488 us timeout 50000us min/avg/max/std-dev: 50025/59198.781/61234/2680.975 us timeout 25000us min/avg/max/std-dev: 28997/29999.529/31023/200.045 us timeout 12500us min/avg/max/std-dev: 17508/20103.311/27802/896.630 us timeout 6250us min/avg/max/std-dev: 10026/18596.189/23655/3354.573 us timeout 3125us min/avg/max/std-dev: 10087/18304.020/21226/3679.233 us timeout 1562us min/avg/max/std-dev: 10059/19395.580/20615/2335.428 us timeout 781us min/avg/max/std-dev: 10038/19299.439/28400/2792.181 us timeout 390us min/avg/max/std-dev: 10193/19502.061/21132/2122.942 us timeout 195us min/avg/max/std-dev: 10068/19297.430/21386/2517.788 us timeout 97us min/avg/max/std-dev: 10214/19799.789/20804/1372.321 us timeout 48us min/avg/max/std-dev: 10032/19399.801/28896/2668.078 us timeout 24us min/avg/max/std-dev: 10106/19599.900/20936/1930.546 us timeout 12us min/avg/max/std-dev: 10203/19799.570/20952/1379.133 us timeout 6us min/avg/max/std-dev: 10047/19799.711/21452/1406.507 us timeout 3us min/avg/max/std-dev: 10035/18699.750/20984/3237.439 us timeout 1us min/avg/max/std-dev: 10036/19499.779/20631/2148.104 us ITIMER_VIRTUAL timeout 800000us min/avg/max/std-dev: 766035/802268.312/860000/15187.871 us timeout 400000us min/avg/max/std-dev: 372155/400825.844/497840/14646.898 us timeout 200000us min/avg/max/std-dev: 182798/200070.953/217841/6382.939 us timeout 100000us min/avg/max/std-dev: 85393/100599.352/118195/5079.172 us timeout 50000us min/avg/max/std-dev: 32158/49660.000/62153/3548.212 us timeout 25000us min/avg/max/std-dev: 22158/30199.730/39995/2776.258 us timeout 12500us min/avg/max/std-dev: 13231/20539.410/33248/3425.671 us timeout 6250us min/avg/max/std-dev: 2534/9999.680/20004/2506.703 us timeout 3125us min/avg/max/std-dev: 3959/10081.800/20003/1933.720 us timeout 1562us min/avg/max/std-dev: 2160/9845.760/14616/1819.296 us timeout 781us min/avg/max/std-dev: 1798/9971.950/20004/2190.388 us timeout 390us min/avg/max/std-dev: 2184/10481.690/20012/3139.951 us timeout 195us min/avg/max/std-dev: 3234/10045.700/17847/2251.113 us timeout 97us min/avg/max/std-dev: 3201/10353.440/20004/2578.286 us timeout 48us min/avg/max/std-dev: 3214/10099.440/20006/2476.438 us timeout 24us min/avg/max/std-dev: 3235/10145.650/21359/2371.112 us timeout 12us min/avg/max/std-dev: 3258/9971.990/20004/1779.954 us timeout 6us min/avg/max/std-dev: 3240/10081.800/20004/2195.738 us timeout 3us min/avg/max/std-dev: 3255/10017.840/22161/1872.433 us timeout 1us min/avg/max/std-dev: 6043/10427.980/26771/2577.006 us ITIMER_PROF timeout 800000us min/avg/max/std-dev: 773957/825628.500/1291795/65319.603 us timeout 400000us min/avg/max/std-dev: 359999/413765.438/555388/34798.846 us timeout 200000us min/avg/max/std-dev: 163174/203752.922/316906/19732.160 us timeout 100000us min/avg/max/std-dev: 69984/108577.547/309999/31115.503 us timeout 50000us min/avg/max/std-dev: 25432/54867.051/122835/16381.745 us timeout 25000us min/avg/max/std-dev: 17057/31432.080/108412/9305.043 us timeout 12500us min/avg/max/std-dev: 7191/20267.301/33960/4862.938 us timeout 6250us min/avg/max/std-dev: 1730/11271.320/41803/6833.725 us timeout 3125us min/avg/max/std-dev: 3118/10427.890/20008/2959.521 us timeout 1562us min/avg/max/std-dev: 2800/9932.020/22164/3489.845 us timeout 781us min/avg/max/std-dev: 3093/10399.650/23224/3625.505 us timeout 390us min/avg/max/std-dev: 2162/10199.760/30007/3434.499 us timeout 195us min/avg/max/std-dev: 3237/10267.140/20006/2908.820 us timeout 97us min/avg/max/std-dev: 2149/10753.720/69994/6621.012 us timeout 48us min/avg/max/std-dev: 2033/10299.800/20004/2885.025 us timeout 24us min/avg/max/std-dev: 485/10178.170/21315/3291.616 us timeout 12us min/avg/max/std-dev: 3164/9999.390/16836/2610.197 us timeout 6us min/avg/max/std-dev: 2158/9721.350/20005/2925.856 us timeout 3us min/avg/max/std-dev: 3147/10717.670/20005/3186.014 us timeout 1us min/avg/max/std-dev: 1774/10181.730/26038/3625.016 us After: ITIMER_REAL timeout 800000us min/avg/max/std-dev: 803100/803985.938/804058/205.714 us timeout 400000us min/avg/max/std-dev: 400952/402097.844/407683/719.658 us timeout 200000us min/avg/max/std-dev: 200209/201099.375/209316/854.072 us timeout 100000us min/avg/max/std-dev: 100197/100499.148/100800/69.824 us timeout 50000us min/avg/max/std-dev: 50024/50350.051/59947/965.817 us timeout 25000us min/avg/max/std-dev: 29356/30149.439/30922/130.371 us timeout 12500us min/avg/max/std-dev: 20045/20099.689/20155/13.412 us timeout 6250us min/avg/max/std-dev: 8271/10150.280/16362/769.947 us timeout 3125us min/avg/max/std-dev: 9608/10049.960/10491/119.870 us timeout 1562us min/avg/max/std-dev: 8076/10049.690/12737/412.012 us timeout 781us min/avg/max/std-dev: 9541/10050.100/10559/137.557 us timeout 390us min/avg/max/std-dev: 9663/10049.610/10448/115.429 us timeout 195us min/avg/max/std-dev: 9729/10049.820/10373/46.558 us timeout 97us min/avg/max/std-dev: 9732/10049.860/10368/45.814 us timeout 48us min/avg/max/std-dev: 9738/10049.810/10362/46.385 us timeout 24us min/avg/max/std-dev: 9615/10049.620/10485/117.845 us timeout 12us min/avg/max/std-dev: 9739/10049.780/10359/44.860 us timeout 6us min/avg/max/std-dev: 9730/10050.020/10368/46.513 us timeout 3us min/avg/max/std-dev: 9730/10049.850/10371/46.334 us timeout 1us min/avg/max/std-dev: 9729/10049.920/10369/46.450 us ITIMER_VIRTUAL timeout 800000us min/avg/max/std-dev: 789569/804457.438/830156/5440.643 us timeout 400000us min/avg/max/std-dev: 391946/402120.188/410366/3031.344 us timeout 200000us min/avg/max/std-dev: 194356/200088.641/204765/1108.089 us timeout 100000us min/avg/max/std-dev: 91674/99899.289/104355/1100.726 us timeout 50000us min/avg/max/std-dev: 45647/50121.762/60004/1267.733 us timeout 25000us min/avg/max/std-dev: 27787/29999.711/32218/313.228 us timeout 12500us min/avg/max/std-dev: 8337/19799.750/26567/1590.757 us timeout 6250us min/avg/max/std-dev: 3424/10012.570/18332/1096.381 us timeout 3125us min/avg/max/std-dev: 9999/10010.560/10046/19.419 us timeout 1562us min/avg/max/std-dev: 9997/9999.860/10000/0.974 us timeout 781us min/avg/max/std-dev: 9998/9999.890/10000/2.649 us timeout 390us min/avg/max/std-dev: 8241/10022.020/13976/434.222 us timeout 195us min/avg/max/std-dev: 9995/9999.840/10000/3.332 us timeout 97us min/avg/max/std-dev: 3436/9934.190/10001/653.082 us timeout 48us min/avg/max/std-dev: 9994/9999.820/10000/-nan us timeout 24us min/avg/max/std-dev: 9997/10043.440/14358/433.618 us timeout 12us min/avg/max/std-dev: 9996/9999.850/10000/2.791 us timeout 6us min/avg/max/std-dev: 9999/9999.900/10001/-nan us timeout 3us min/avg/max/std-dev: 9997/10039.640/12218/280.492 us timeout 1us min/avg/max/std-dev: 9700/9999.790/10300/43.534 us ITIMER_PROF timeout 800000us min/avg/max/std-dev: 791669/800155.375/809999/2688.569 us timeout 400000us min/avg/max/std-dev: 391674/400119.594/408324/2849.512 us timeout 200000us min/avg/max/std-dev: 187787/199916.219/206569/1862.663 us timeout 100000us min/avg/max/std-dev: 91676/99899.297/108328/1663.900 us timeout 50000us min/avg/max/std-dev: 41678/49916.352/58332/1439.452 us timeout 25000us min/avg/max/std-dev: 28327/29999.699/31678/240.663 us timeout 12500us min/avg/max/std-dev: 11666/20199.760/29999/1845.135 us timeout 6250us min/avg/max/std-dev: 9994/9999.850/10000/2.791 us timeout 3125us min/avg/max/std-dev: 9997/9999.860/10001/0.974 us timeout 1562us min/avg/max/std-dev: 9995/9999.880/10007/1.526 us timeout 781us min/avg/max/std-dev: 9700/10083.090/18330/829.971 us timeout 390us min/avg/max/std-dev: 3435/9916.600/10298/676.252 us timeout 195us min/avg/max/std-dev: 9996/9999.880/10001/1.526 us timeout 97us min/avg/max/std-dev: 9984/10043.390/14372/435.059 us timeout 48us min/avg/max/std-dev: 9994/9999.860/10000/0.974 us timeout 24us min/avg/max/std-dev: 2240/9856.300/10000/1006.313 us timeout 12us min/avg/max/std-dev: 1628/9999.790/18330/1181.026 us timeout 6us min/avg/max/std-dev: 1642/9999.750/18329/1179.956 us timeout 3us min/avg/max/std-dev: 9986/9999.860/10013/0.974 us timeout 1us min/avg/max/std-dev: 9998/10065.560/16573/654.033 us Looking at the numbers I think the result is actually what we want. Once the timeout is below 1/HZs the avg time slept is pretty much 1 tick. The profiling and virtual timers seem to be fairly close to before on avg but the std-dec seems to be better but this could be just my luck. Below the timer.c code I used. -- :wq Claudio #include <err.h> #include <errno.h> #include <math.h> #include <signal.h> #include <stdio.h> #include <unistd.h> #include <sys/time.h> #define LOOPCOUNT 100 volatile sig_atomic_t trigger; void sighdlr(int signum) { trigger = signum; } static void test(int which) { struct itimerval new_timer = { 0 }; struct timeval str, end; long long count, d, sum, min, max, tsumsq; long timeout; double avg, dev, dummy; for (timeout = 800000; timeout != 0; timeout /= 2) { new_timer.it_value.tv_usec = timeout; min = 1000000000; max = 0; sum = 0; tsumsq = 0; for (count = 0; count != LOOPCOUNT; count++) { trigger = 0; gettimeofday(&str, NULL); setitimer(which, &new_timer, NULL); dummy = 1.0; while (trigger == 0) { dummy += sqrt(dummy); } gettimeofday(&end, NULL); d = (end.tv_sec - str.tv_sec) * 1000000 + end.tv_usec - str.tv_usec; sum += d; tsumsq += d * d; if (d < min) min = d; if (d > max) max = d; } avg = (float) sum / count; dev = sqrt((float) tsumsq / count - avg * avg); printf("timeout %7ldus min/avg/max/std-dev: %lld/%.3f/" "%lld/%.3f us\n", timeout, min, avg, max, dev); } } int main(int argc, char ** argv) { signal(SIGALRM, sighdlr); signal(SIGVTALRM, sighdlr); signal(SIGPROF, sighdlr); printf("Running for %d loops\n\n", LOOPCOUNT); printf("ITIMER_REAL\n"); test(ITIMER_REAL); printf("ITIMER_VIRTUAL\n"); test(ITIMER_VIRTUAL); printf("ITIMER_PROF\n"); test(ITIMER_PROF); }