Hi Subrata
On Thu, 2 Apr 2009 22:05:51 +0530
Subrata Modak <[email protected]> wrote:
> Thanks for this test program. We would like to test this on some of our
> kernels. However, i have a question. The % of errors you have shown pre and
> post patch. If i use this test as a functional verification test, how much %
> error can be considered as safe/pass ?
Mmm, precisely is hard to say, this rather depend what kind of applications
system is running. IMHO if is more than 2% is not so good, more than 20% is
really bad.
Remember, program need to run on idle system otherwise measurements
are broken. Perhaps also busy loop counter need to be tunable to generate
reasonable delay (not too small and not big) on different CPU clocks.
> And can your test be included inside LTP (http://ltp.sourceforge.net/) under
> GPL ?
No problem with LTP inclusion and GPL.
I attached another program with, maybe you find it more useful than this one,
it also test POSIX 1b timer.
Signed-off-by: Stanislaw Gruszka <[email protected]>
> > =============================================================================
> >
> > /*
> > * Measures the systematic error of a periodic timer.
> > * Best run on an otherwise idle system, so that the simplifying assumption
> > * cpu_time_consumed_by_this_process==real_elapsed_time holds.
> > */
> >
> > #include <sys/time.h>
> > #include <signal.h>
> > #include <stdio.h>
> > #include <stdlib.h>
> >
> > /* This is what profiling with gcc -pg uses: */
> > #define SIGNAL SIGPROF
> > #define ITIMER ITIMER_PROF
> >
> > //#define SIGNAL SIGVTALRM
> > //#define ITIMER ITIMER_VIRTUAL
> >
> > //#define SIGNAL SIGALRM
> > //#define ITIMER ITIMER_REAL
> >
> > #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
> >
> > const int test_periods_us[] = {
> > 10000, /* glibc's value for x86(_64) */
> > 9998, /* this value would cause a much smaller error */
> > 1000 /* and this is what is used for profiling on ia64 */
> > };
> >
> > volatile int prof_counter;
> >
> > void handler(int signr)
> > {
> > prof_counter++;
> > }
> >
> > void test_func(void)
> > {
> > int i = 0;
> > int count = 0;
> >
> > for(i=0; i<2000000000; i++)
> > count++;
> > }
> >
> > double timeval_diff(const struct timeval *start, const struct timeval *end)
> > {
> > return (end->tv_sec - start->tv_sec) + (end->tv_usec -
> > start->tv_usec)/1000000.0;
> > }
> >
> > void measure_itimer_error(int period_us)
> > {
> > struct sigaction act;
> > struct timeval start, end;
> > double real_time, counted_time;
> >
> > prof_counter = 0;
> >
> > /* setup a periodic timer */
> > struct timeval period_tv = {
> > .tv_sec = 0,
> > .tv_usec = period_us
> > };
> > struct itimerval timer = {
> > .it_interval = period_tv,
> > .it_value = period_tv
> > };
> > act.sa_handler = handler;
> > sigemptyset(&act.sa_mask);
> > act.sa_flags = 0;
> > if (sigaction(SIGNAL, &act, NULL) < 0) {
> > printf("sigaction failed\n");
> > exit(1);
> > }
> > if (setitimer(ITIMER, &timer, NULL) < 0) {
> > perror("setitimer");
> > exit(1);
> > }
> >
> > /* run a busy loop and measure it */
> > gettimeofday(&start, NULL);
> > test_func();
> > gettimeofday(&end, NULL);
> >
> > /* disable the timer */
> > timer.it_value.tv_usec = 0;
> > if (setitimer(ITIMER, &timer, NULL) < 0) {
> > perror("setitimer");
> > exit(1);
> > }
> >
> > counted_time = prof_counter * period_us / 1000000.0;
> > real_time = timeval_diff(&start, &end);
> > printf("Requested a period of %d us and counted to %d, that should
> > be %.2f s\n",
> > period_us, prof_counter, counted_time);
> > printf("Meanwhile real time elapsed: %.2f s\n", real_time);
> > printf("The error was %.1f %%\n\n", (counted_time/real_time -
> > 1.0)*100.0);
> > }
> >
> > int main()
> > {
> > int i;
> > for (i=0; i<ARRAY_SIZE(test_periods_us); i++)
> > measure_itimer_error(test_periods_us[i]);
> > return 0;
> > }
> >
> >
> > ===============================================================================
> >
> >
> > [2] TEST PROGRAM RESULTS
> >
> > Test program results for unpatched kernel:
> > ==========================================
> >
> > Requested a period of 10000 us and counted to 644, that should be 6.44 s
> > Meanwhile real time elapsed: 7.10 s
> > The error was -9.2 %
> >
> > Requested a period of 9998 us and counted to 708, that should be 7.08 s
> > Meanwhile real time elapsed: 7.08 s
> > The error was -0.1 %
> >
> > Requested a period of 1000 us and counted to 3542, that should be 3.54 s
> > Meanwhile real time elapsed: 7.09 s
> > The error was -50.1 %
> >
> > To fix situation we wrote two patches, first just simplify code related
> > with itimers. Second
> >
> > Test program results after patches applied:
> > ===========================================
> >
> > Requested a period of 10000 us and counted to 708, that should be 7.08 s
> > Meanwhile real time elapsed: 7.10 s
> > The error was -0.2 %
> >
> > Requested a period of 9998 us and counted to 709, that should be 7.09 s
> > Meanwhile real time elapsed: 7.10 s
> > The error was -0.1 %
> >
> > Requested a period of 1000 us and counted to 7100, that should be 7.10 s
> > Meanwhile real time elapsed: 7.11 s
> > The error was -0.1 %
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at http://www.tux.org/lkml/
> >
>
>
>
/*
* Measures the systematic error of a periodic timer.
* Best run on an otherwise idle system, so that the simplifying assumption
* cpu_time_consumed_by_this_process==real_elapsed_time holds.
*/
#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
/* This is what profiling with gcc -pg uses: */
#define SIGNAL SIGPROF
#define ITIMER ITIMER_PROF
//#define SIGNAL SIGVTALRM
//#define ITIMER ITIMER_VIRTUAL
//#define SIGNAL SIGALRM
//#define ITIMER ITIMER_REAL
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
const int test_periods_us[] = {
10000, /* glibc's value for x86(_64) */
9998, /* this value would cause a much smaller error */
1000, /* and this is what is used for profiling on ia64 */
11111, /* just stupid testcases */
21315,
1500,
15000,
50000,
500,
};
volatile int prof_counter;
void handler(int signr)
{
prof_counter++;
}
void test_func(void)
{
int i = 0;
int count = 0;
for(i=0; i<2000000000; i++)
count++;
}
double timeval_diff(const struct timeval *start, const struct timeval *end)
{
return (end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec)/1000000.0;
}
void measure_itimer_error(int period_us, int api)
{
struct sigaction act;
struct timeval start, end;
struct sigevent evt;
double real_time, counted_time;
timer_t tid;
prof_counter = 0;
struct timeval period_tv = {
.tv_sec = 0,
.tv_usec = period_us
};
struct itimerval timer_val = {
.it_interval = period_tv,
.it_value = period_tv
};
struct timespec period_ts = {
.tv_sec = 0,
.tv_nsec = period_us * 1000,
};
struct itimerspec timer_spec = {
.it_interval = period_ts,
.it_value = period_ts
};
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGNAL, &act, NULL) < 0) {
printf("sigaction failed\n");
exit(1);
}
/* setup a periodic timer */
if (api) {
memset(&evt, 0, sizeof(evt));
evt.sigev_notify = SIGEV_SIGNAL;
evt.sigev_signo = SIGNAL;
if (timer_create(CLOCK_PROCESS_CPUTIME_ID, &evt, &tid) < 0) {
perror("timer_create");
exit(1);
}
if (timer_settime(tid, 0, &timer_spec, NULL) < 0) {
perror("timer_settime");
exit(1);
}
} else {
if (setitimer(ITIMER, &timer_val, NULL) < 0) {
perror("setitimer");
exit(1);
}
}
/* run a busy loop and measure it */
gettimeofday(&start, NULL);
test_func();
gettimeofday(&end, NULL);
/* disable the timer */
if (api) {
memset(&timer_spec, 0, sizeof(timer_spec));
if (timer_settime(tid, 0, &timer_spec, NULL) < 0) {
perror("timer_settime");
exit(1);
}
if (timer_delete(tid) < 0) {
perror("timer_delete");
exit(1);
}
} else {
timer_val.it_value.tv_usec = 0;
if (setitimer(ITIMER, &timer_val, NULL) < 0) {
perror("setitimer");
exit(1);
}
}
counted_time = prof_counter * period_us / 1000000.0;
real_time = timeval_diff(&start, &end);
/*
printf("Requested a period of %d us and counted to %d, that should be %.2f s\n",
period_us, prof_counter, counted_time);
printf("Meanwhile real time elapsed: %.2f s\n", real_time);
printf("The error was %.1f %%\n\n", (counted_time/real_time - 1.0)*100.0);
*/
printf("Period %d:\tcounted time %.2f , real time %.2f , error %.1f %%\n",
period_us, counted_time, real_time, (counted_time/real_time - 1.0)*100.0);
}
int main()
{
int i;
printf("setitimer API:\n");
for (i=0; i<ARRAY_SIZE(test_periods_us); i++)
measure_itimer_error(test_periods_us[i], 0);
printf("timer_* API:\n");
for (i=0; i<ARRAY_SIZE(test_periods_us); i++)
measure_itimer_error(test_periods_us[i], 1);
return 0;
}
------------------------------------------------------------------------------
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list