All of lore.kernel.org
 help / color / mirror / Atom feed
* Non RT threads impact on RT thread
@ 2018-05-22 10:00 Jordan Palacios
  2018-05-22 10:20 ` AW: " Lampersperger Andreas
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Jordan Palacios @ 2018-05-22 10:00 UTC (permalink / raw)
  To: linux-rt-users

Hello,

We are currently running a version of the linux kernel (3.18.24) with
the RT-PREEMPT patch. In our system there are several non RT tasks and
one RT task. The RT process runs in the FIFO scheduler with 95
priority and a control loop of 1ms.

We have achieved latencies of about 5us which are perfect for us.

Our issue is that the RT task sometimes misses one of its cycles due
to an unexpected very long execution time of its control loop. In our
system this is a critical failure.

We enabled tracing in the kernel and started measuring the execution
time of the RT thread. The execution time is quite constant (about
200us), which random spikes every now and then. Thing is, the less non
RT tasks running in the system the better the RT task behaves.

We wrote a very simple RT application that does some light work and
writes its execution time using the trace_marker. Execution time is
constant but IO intensive stuff, like a stress --io 32 or a hdparm,
will have and impact on its execution time. This is surprising because
the test does not any kind of work related to IO. Nor does the RT task
in our system for that matter.

Our question is: Is this behaviour normal? Why are non RT tasks
affecting the RT task performance? Is there any other kind of test
that we could run that would shed some light on this issue?

Thanks in advance.

Jordan.



#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sstream>
#include <math.h>
#include <unistd.h>
#include <stdarg.h>

typedef long long NANO_TIME;
typedef struct timespec TIME_SPEC;

static const long int INTERVAL = 1000000LL; // 1ms

static TIME_SPEC nano2timespec(NANO_TIME hrt)
{
  TIME_SPEC timevl;
  timevl.tv_sec = hrt / 1000000000LL;
  timevl.tv_nsec = hrt % 1000000000LL;
  return timevl;
}

static double to_us(NANO_TIME ns)
{
  return static_cast<double>(ns) / 1000.0;
}

static NANO_TIME get_time_ns(void)
{
  TIME_SPEC tv;
  clock_gettime(CLOCK_REALTIME, &tv);
  return NANO_TIME(tv.tv_sec) * 1000000000LL + NANO_TIME(tv.tv_nsec);
}

static const unsigned int WORK_SIZE = 10000;

void do_work()
{
  unsigned int i = 0;
  double aux = 2;

  // do some stuff to use cpu
  while (i < WORK_SIZE)
  {
    aux = pow(aux, i);
    ++i;
  }
}

int trace_fd = -1;

void trace_write(const char* fmt, ...)
{
  va_list ap;
  char buf[256];
  int n;

  if (trace_fd < 0)
    return;

  va_start(ap, fmt);
  n = vsnprintf(buf, 256, fmt, ap);
  va_end(ap);

  write(trace_fd, buf, n);
}

void* thread_func(void* /*data*/)
{
  pid_t tid = syscall(__NR_gettid);
  printf("pthread joined. TID %i \n", tid);

  TIME_SPEC ts_next;
  NANO_TIME wake, init, after_work;

  wake = get_time_ns() + INTERVAL;
  ts_next = nano2timespec(wake);

  while (true)
  {
    init = get_time_ns();

    if (init < wake)
    {
      do_work();
      after_work = get_time_ns();

      const double exec_time = to_us(after_work - init);
      trace_write("rt_test_exec_time - %f", exec_time);
    }
    else
    {
      printf("overrun detected\n");
    }

    clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(ts_next), NULL);
    wake = wake + INTERVAL;
    ts_next = nano2timespec(wake);
  }
  return NULL;
}

int main(int /*argc*/, char* /*argv*/[])
{
  struct sched_param param;
  pthread_attr_t attr;
  pthread_t thread;
  int ret;

  /* Lock memory */
  if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
  {
    printf("mlockall failed: %m\n");
    exit(-2);
  }

  /* Allocate all the memory required by the process */
  if (!malloc(100 * 1048576))  // 100MB
  {
    printf("malloc failed\n");
    exit(-3);
  }

  /* Initialize pthread attributes (default values) */
  ret = pthread_attr_init(&attr);
  if (ret)
  {
    printf("init pthread attributes failed\n");
    return ret;
  }

  /* Set a specific stack size  */
  ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN * 100);
  if (ret)
  {
    printf("pthread setstacksize failed\n");
    return ret;
  }

  /* Set scheduler policy and priority of pthread */
  ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
  if (ret)
  {
    printf("pthread setschedpolicy failed\n");
    return ret;
  }

  param.sched_priority = 95;
  ret = pthread_attr_setschedparam(&attr, &param);
  if (ret)
  {
    printf("pthread setschedparam failed\n");
    return ret;
  }

  /* Use scheduling parameters of attr */
  ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
  if (ret)
  {
    printf("pthread setinheritsched failed\n");
    return ret;
  }

  /* Create a pthread with specified attributes */
  ret = pthread_create(&thread, &attr, thread_func, NULL);
  if (ret)
  {
    printf("create pthread failed\n");
    return ret;
  }

  /* Open tracer_marker */
  trace_fd = open("/tracing/trace_marker", O_WRONLY);
  if (trace_fd == -1)
  {
    printf("trace_marker open failed\n");
    return ret;
  }

  system("echo 1 > /tracing/tracing_on");             // enable tracing
  system("echo nop > /tracing/current_tracer");       // reset trace
  system("echo function > /tracing/current_tracer");  // use function tracer
  system("echo 1 > /tracing/events/enable");          // enable all events

  /* Join the thread and wait until it is done */
  ret = pthread_join(thread, NULL);
  if (ret)
    printf("join pthread failed: %m\n");

  system("echo 0 > /tracing/tracing_on");     // disable tracing
  system("echo 0 > /tracing/events/enable");  // disable all events

  return ret;
}

^ permalink raw reply	[flat|nested] 13+ messages in thread

* AW: Non RT threads impact on RT thread
  2018-05-22 10:00 Non RT threads impact on RT thread Jordan Palacios
@ 2018-05-22 10:20 ` Lampersperger Andreas
  2018-05-22 11:03   ` Jordan Palacios
  2018-05-22 12:56   ` AW: " Gene Heskett
  2018-05-22 12:51 ` Gene Heskett
  2018-05-22 18:34 ` Julia Cartwright
  2 siblings, 2 replies; 13+ messages in thread
From: Lampersperger Andreas @ 2018-05-22 10:20 UTC (permalink / raw)
  To: Jordan Palacios, linux-rt-users

Hello Jordan,

IMHO this is because the non-RT Tasks uses the same CPU and therefore the same cache. Especially when your CPU has hyperthreading also the L1-Cache is shared between RT and non-RT. 
Try using different CPUs for RT and non-RT tasks und disable hyperthreading (in the bios).

@all: When I'm not correct, I would be very pleased if somebody let me know about this.

Best regards
Andreas

-----Ursprüngliche Nachricht-----
Von: linux-rt-users-owner@vger.kernel.org [mailto:linux-rt-users-owner@vger.kernel.org] Im Auftrag von Jordan Palacios
Gesendet: Dienstag, 22. Mai 2018 12:00
An: linux-rt-users@vger.kernel.org
Betreff: Non RT threads impact on RT thread

Hello,

We are currently running a version of the linux kernel (3.18.24) with the RT-PREEMPT patch. In our system there are several non RT tasks and one RT task. The RT process runs in the FIFO scheduler with 95 priority and a control loop of 1ms.

We have achieved latencies of about 5us which are perfect for us.

Our issue is that the RT task sometimes misses one of its cycles due to an unexpected very long execution time of its control loop. In our system this is a critical failure.

We enabled tracing in the kernel and started measuring the execution time of the RT thread. The execution time is quite constant (about 200us), which random spikes every now and then. Thing is, the less non RT tasks running in the system the better the RT task behaves.

We wrote a very simple RT application that does some light work and writes its execution time using the trace_marker. Execution time is constant but IO intensive stuff, like a stress --io 32 or a hdparm, will have and impact on its execution time. This is surprising because the test does not any kind of work related to IO. Nor does the RT task in our system for that matter.

Our question is: Is this behaviour normal? Why are non RT tasks affecting the RT task performance? Is there any other kind of test that we could run that would shed some light on this issue?

Thanks in advance.

Jordan.



#include <limits.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sstream>
#include <math.h>
#include <unistd.h>
#include <stdarg.h>

typedef long long NANO_TIME;
typedef struct timespec TIME_SPEC;

static const long int INTERVAL = 1000000LL; // 1ms

static TIME_SPEC nano2timespec(NANO_TIME hrt) {
  TIME_SPEC timevl;
  timevl.tv_sec = hrt / 1000000000LL;
  timevl.tv_nsec = hrt % 1000000000LL;
  return timevl;
}

static double to_us(NANO_TIME ns)
{
  return static_cast<double>(ns) / 1000.0; }

static NANO_TIME get_time_ns(void)
{
  TIME_SPEC tv;
  clock_gettime(CLOCK_REALTIME, &tv);
  return NANO_TIME(tv.tv_sec) * 1000000000LL + NANO_TIME(tv.tv_nsec); }

static const unsigned int WORK_SIZE = 10000;

void do_work()
{
  unsigned int i = 0;
  double aux = 2;

  // do some stuff to use cpu
  while (i < WORK_SIZE)
  {
    aux = pow(aux, i);
    ++i;
  }
}

int trace_fd = -1;

void trace_write(const char* fmt, ...)
{
  va_list ap;
  char buf[256];
  int n;

  if (trace_fd < 0)
    return;

  va_start(ap, fmt);
  n = vsnprintf(buf, 256, fmt, ap);
  va_end(ap);

  write(trace_fd, buf, n);
}

void* thread_func(void* /*data*/)
{
  pid_t tid = syscall(__NR_gettid);
  printf("pthread joined. TID %i \n", tid);

  TIME_SPEC ts_next;
  NANO_TIME wake, init, after_work;

  wake = get_time_ns() + INTERVAL;
  ts_next = nano2timespec(wake);

  while (true)
  {
    init = get_time_ns();

    if (init < wake)
    {
      do_work();
      after_work = get_time_ns();

      const double exec_time = to_us(after_work - init);
      trace_write("rt_test_exec_time - %f", exec_time);
    }
    else
    {
      printf("overrun detected\n");
    }

    clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(ts_next), NULL);
    wake = wake + INTERVAL;
    ts_next = nano2timespec(wake);
  }
  return NULL;
}

int main(int /*argc*/, char* /*argv*/[]) {
  struct sched_param param;
  pthread_attr_t attr;
  pthread_t thread;
  int ret;

  /* Lock memory */
  if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
  {
    printf("mlockall failed: %m\n");
    exit(-2);
  }

  /* Allocate all the memory required by the process */
  if (!malloc(100 * 1048576))  // 100MB
  {
    printf("malloc failed\n");
    exit(-3);
  }

  /* Initialize pthread attributes (default values) */
  ret = pthread_attr_init(&attr);
  if (ret)
  {
    printf("init pthread attributes failed\n");
    return ret;
  }

  /* Set a specific stack size  */
  ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN * 100);
  if (ret)
  {
    printf("pthread setstacksize failed\n");
    return ret;
  }

  /* Set scheduler policy and priority of pthread */
  ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
  if (ret)
  {
    printf("pthread setschedpolicy failed\n");
    return ret;
  }

  param.sched_priority = 95;
  ret = pthread_attr_setschedparam(&attr, &param);
  if (ret)
  {
    printf("pthread setschedparam failed\n");
    return ret;
  }

  /* Use scheduling parameters of attr */
  ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
  if (ret)
  {
    printf("pthread setinheritsched failed\n");
    return ret;
  }

  /* Create a pthread with specified attributes */
  ret = pthread_create(&thread, &attr, thread_func, NULL);
  if (ret)
  {
    printf("create pthread failed\n");
    return ret;
  }

  /* Open tracer_marker */
  trace_fd = open("/tracing/trace_marker", O_WRONLY);
  if (trace_fd == -1)
  {
    printf("trace_marker open failed\n");
    return ret;
  }

  system("echo 1 > /tracing/tracing_on");             // enable tracing
  system("echo nop > /tracing/current_tracer");       // reset trace
  system("echo function > /tracing/current_tracer");  // use function tracer
  system("echo 1 > /tracing/events/enable");          // enable all events

  /* Join the thread and wait until it is done */
  ret = pthread_join(thread, NULL);
  if (ret)
    printf("join pthread failed: %m\n");

  system("echo 0 > /tracing/tracing_on");     // disable tracing
  system("echo 0 > /tracing/events/enable");  // disable all events

  return ret;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@vger.kernel.org More majordomo info at  http://vger.kernel.org/majordomo-info.html

------------------------------------------------------------------------------------------------------
Registergericht: Traunstein / Registry Court: HRB 275 - Sitz / Head Office: Traunreut
Aufsichtsratsvorsitzender / Chairman of Supervisory Board: Rainer Burkhard
Geschäftsführung / Management Board: Thomas Sesselmann (Vorsitzender / Chairman),
Hubert Ermer, Michael Grimm, Lutz Rissing

E-Mail Haftungsausschluss / E-Mail Disclaimer: http://www.heidenhain.de/disclaimer

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-22 10:20 ` AW: " Lampersperger Andreas
@ 2018-05-22 11:03   ` Jordan Palacios
  2018-05-22 12:56   ` AW: " Gene Heskett
  1 sibling, 0 replies; 13+ messages in thread
From: Jordan Palacios @ 2018-05-22 11:03 UTC (permalink / raw)
  To: Lampersperger Andreas; +Cc: linux-rt-users

Hello Andreas,

Thanks for your response.

Our system has hyperthreading currently disabled. In fact we have
tested and applied most of the tips given here:
http://linuxrealtime.org/index.php/Improving_the_Real-Time_Properties

The RT task is running in an isolated CPU (using cset) but even stuff
like hdparm (which is used for testing hard drives) manages to somehow
impact the RT performance.

Kind regards,
Jordan.

On 22 May 2018 at 12:20, Lampersperger Andreas
<lampersperger.andreas@heidenhain.de> wrote:
> Hello Jordan,
>
> IMHO this is because the non-RT Tasks uses the same CPU and therefore the same cache. Especially when your CPU has hyperthreading also the L1-Cache is shared between RT and non-RT.
> Try using different CPUs for RT and non-RT tasks und disable hyperthreading (in the bios).
>
> @all: When I'm not correct, I would be very pleased if somebody let me know about this.
>
> Best regards
> Andreas
>
> -----Ursprüngliche Nachricht-----
> Von: linux-rt-users-owner@vger.kernel.org [mailto:linux-rt-users-owner@vger.kernel.org] Im Auftrag von Jordan Palacios
> Gesendet: Dienstag, 22. Mai 2018 12:00
> An: linux-rt-users@vger.kernel.org
> Betreff: Non RT threads impact on RT thread
>
> Hello,
>
> We are currently running a version of the linux kernel (3.18.24) with the RT-PREEMPT patch. In our system there are several non RT tasks and one RT task. The RT process runs in the FIFO scheduler with 95 priority and a control loop of 1ms.
>
> We have achieved latencies of about 5us which are perfect for us.
>
> Our issue is that the RT task sometimes misses one of its cycles due to an unexpected very long execution time of its control loop. In our system this is a critical failure.
>
> We enabled tracing in the kernel and started measuring the execution time of the RT thread. The execution time is quite constant (about 200us), which random spikes every now and then. Thing is, the less non RT tasks running in the system the better the RT task behaves.
>
> We wrote a very simple RT application that does some light work and writes its execution time using the trace_marker. Execution time is constant but IO intensive stuff, like a stress --io 32 or a hdparm, will have and impact on its execution time. This is surprising because the test does not any kind of work related to IO. Nor does the RT task in our system for that matter.
>
> Our question is: Is this behaviour normal? Why are non RT tasks affecting the RT task performance? Is there any other kind of test that we could run that would shed some light on this issue?
>
> Thanks in advance.
>
> Jordan.
>
>
>
> #include <limits.h>
> #include <pthread.h>
> #include <sched.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/syscall.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <sstream>
> #include <math.h>
> #include <unistd.h>
> #include <stdarg.h>
>
> typedef long long NANO_TIME;
> typedef struct timespec TIME_SPEC;
>
> static const long int INTERVAL = 1000000LL; // 1ms
>
> static TIME_SPEC nano2timespec(NANO_TIME hrt) {
>   TIME_SPEC timevl;
>   timevl.tv_sec = hrt / 1000000000LL;
>   timevl.tv_nsec = hrt % 1000000000LL;
>   return timevl;
> }
>
> static double to_us(NANO_TIME ns)
> {
>   return static_cast<double>(ns) / 1000.0; }
>
> static NANO_TIME get_time_ns(void)
> {
>   TIME_SPEC tv;
>   clock_gettime(CLOCK_REALTIME, &tv);
>   return NANO_TIME(tv.tv_sec) * 1000000000LL + NANO_TIME(tv.tv_nsec); }
>
> static const unsigned int WORK_SIZE = 10000;
>
> void do_work()
> {
>   unsigned int i = 0;
>   double aux = 2;
>
>   // do some stuff to use cpu
>   while (i < WORK_SIZE)
>   {
>     aux = pow(aux, i);
>     ++i;
>   }
> }
>
> int trace_fd = -1;
>
> void trace_write(const char* fmt, ...)
> {
>   va_list ap;
>   char buf[256];
>   int n;
>
>   if (trace_fd < 0)
>     return;
>
>   va_start(ap, fmt);
>   n = vsnprintf(buf, 256, fmt, ap);
>   va_end(ap);
>
>   write(trace_fd, buf, n);
> }
>
> void* thread_func(void* /*data*/)
> {
>   pid_t tid = syscall(__NR_gettid);
>   printf("pthread joined. TID %i \n", tid);
>
>   TIME_SPEC ts_next;
>   NANO_TIME wake, init, after_work;
>
>   wake = get_time_ns() + INTERVAL;
>   ts_next = nano2timespec(wake);
>
>   while (true)
>   {
>     init = get_time_ns();
>
>     if (init < wake)
>     {
>       do_work();
>       after_work = get_time_ns();
>
>       const double exec_time = to_us(after_work - init);
>       trace_write("rt_test_exec_time - %f", exec_time);
>     }
>     else
>     {
>       printf("overrun detected\n");
>     }
>
>     clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(ts_next), NULL);
>     wake = wake + INTERVAL;
>     ts_next = nano2timespec(wake);
>   }
>   return NULL;
> }
>
> int main(int /*argc*/, char* /*argv*/[]) {
>   struct sched_param param;
>   pthread_attr_t attr;
>   pthread_t thread;
>   int ret;
>
>   /* Lock memory */
>   if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
>   {
>     printf("mlockall failed: %m\n");
>     exit(-2);
>   }
>
>   /* Allocate all the memory required by the process */
>   if (!malloc(100 * 1048576))  // 100MB
>   {
>     printf("malloc failed\n");
>     exit(-3);
>   }
>
>   /* Initialize pthread attributes (default values) */
>   ret = pthread_attr_init(&attr);
>   if (ret)
>   {
>     printf("init pthread attributes failed\n");
>     return ret;
>   }
>
>   /* Set a specific stack size  */
>   ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN * 100);
>   if (ret)
>   {
>     printf("pthread setstacksize failed\n");
>     return ret;
>   }
>
>   /* Set scheduler policy and priority of pthread */
>   ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
>   if (ret)
>   {
>     printf("pthread setschedpolicy failed\n");
>     return ret;
>   }
>
>   param.sched_priority = 95;
>   ret = pthread_attr_setschedparam(&attr, &param);
>   if (ret)
>   {
>     printf("pthread setschedparam failed\n");
>     return ret;
>   }
>
>   /* Use scheduling parameters of attr */
>   ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
>   if (ret)
>   {
>     printf("pthread setinheritsched failed\n");
>     return ret;
>   }
>
>   /* Create a pthread with specified attributes */
>   ret = pthread_create(&thread, &attr, thread_func, NULL);
>   if (ret)
>   {
>     printf("create pthread failed\n");
>     return ret;
>   }
>
>   /* Open tracer_marker */
>   trace_fd = open("/tracing/trace_marker", O_WRONLY);
>   if (trace_fd == -1)
>   {
>     printf("trace_marker open failed\n");
>     return ret;
>   }
>
>   system("echo 1 > /tracing/tracing_on");             // enable tracing
>   system("echo nop > /tracing/current_tracer");       // reset trace
>   system("echo function > /tracing/current_tracer");  // use function tracer
>   system("echo 1 > /tracing/events/enable");          // enable all events
>
>   /* Join the thread and wait until it is done */
>   ret = pthread_join(thread, NULL);
>   if (ret)
>     printf("join pthread failed: %m\n");
>
>   system("echo 0 > /tracing/tracing_on");     // disable tracing
>   system("echo 0 > /tracing/events/enable");  // disable all events
>
>   return ret;
> }
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@vger.kernel.org More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> ------------------------------------------------------------------------------------------------------
> Registergericht: Traunstein / Registry Court: HRB 275 - Sitz / Head Office: Traunreut
> Aufsichtsratsvorsitzender / Chairman of Supervisory Board: Rainer Burkhard
> Geschäftsführung / Management Board: Thomas Sesselmann (Vorsitzender / Chairman),
> Hubert Ermer, Michael Grimm, Lutz Rissing
>
> E-Mail Haftungsausschluss / E-Mail Disclaimer: http://www.heidenhain.de/disclaimer

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-22 10:00 Non RT threads impact on RT thread Jordan Palacios
  2018-05-22 10:20 ` AW: " Lampersperger Andreas
@ 2018-05-22 12:51 ` Gene Heskett
  2018-05-22 18:34 ` Julia Cartwright
  2 siblings, 0 replies; 13+ messages in thread
From: Gene Heskett @ 2018-05-22 12:51 UTC (permalink / raw)
  To: linux-rt-users

On Tuesday 22 May 2018 06:00:27 Jordan Palacios wrote:

> Hello,
>
> We are currently running a version of the linux kernel (3.18.24) with
> the RT-PREEMPT patch. In our system there are several non RT tasks and
> one RT task. The RT process runs in the FIFO scheduler with 95
> priority and a control loop of 1ms.
>
> We have achieved latencies of about 5us which are perfect for us.
>
> Our issue is that the RT task sometimes misses one of its cycles due
> to an unexpected very long execution time of its control loop. In our
> system this is a critical failure.
>
And its a trademark of using the nvidia video driver, which runs with the 
IRQ's disabled, sometimes for hundreds of milliseconds at a time. So use 
the nouveau driver instead, its not guilty of that transgression. You 
may also have to disable the bios "SMI" stuff.

> We enabled tracing in the kernel and started measuring the execution
> time of the RT thread. The execution time is quite constant (about
> 200us), which random spikes every now and then. Thing is, the less non
> RT tasks running in the system the better the RT task behaves.
>
> We wrote a very simple RT application that does some light work and
> writes its execution time using the trace_marker. Execution time is
> constant but IO intensive stuff, like a stress --io 32 or a hdparm,
> will have and impact on its execution time. This is surprising because
> the test does not any kind of work related to IO. Nor does the RT task
> in our system for that matter.
>
> Our question is: Is this behaviour normal? Why are non RT tasks
> affecting the RT task performance? Is there any other kind of test
> that we could run that would shed some light on this issue?
>
LinuxCNC which can run several realtime threads, has latencytest, and at 
least one other way to measure this.

> Thanks in advance.
>
> Jordan.
>
>
>
> #include <limits.h>
> #include <pthread.h>
> #include <sched.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/syscall.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <sstream>
> #include <math.h>
> #include <unistd.h>
> #include <stdarg.h>
>
> typedef long long NANO_TIME;
> typedef struct timespec TIME_SPEC;
>
> static const long int INTERVAL = 1000000LL; // 1ms
>
> static TIME_SPEC nano2timespec(NANO_TIME hrt)
> {
>   TIME_SPEC timevl;
>   timevl.tv_sec = hrt / 1000000000LL;
>   timevl.tv_nsec = hrt % 1000000000LL;
>   return timevl;
> }
>
> static double to_us(NANO_TIME ns)
> {
>   return static_cast<double>(ns) / 1000.0;
> }
>
> static NANO_TIME get_time_ns(void)
> {
>   TIME_SPEC tv;
>   clock_gettime(CLOCK_REALTIME, &tv);
>   return NANO_TIME(tv.tv_sec) * 1000000000LL + NANO_TIME(tv.tv_nsec);
> }
>
> static const unsigned int WORK_SIZE = 10000;
>
> void do_work()
> {
>   unsigned int i = 0;
>   double aux = 2;
>
>   // do some stuff to use cpu
>   while (i < WORK_SIZE)
>   {
>     aux = pow(aux, i);
>     ++i;
>   }
> }
>
> int trace_fd = -1;
>
> void trace_write(const char* fmt, ...)
> {
>   va_list ap;
>   char buf[256];
>   int n;
>
>   if (trace_fd < 0)
>     return;
>
>   va_start(ap, fmt);
>   n = vsnprintf(buf, 256, fmt, ap);
>   va_end(ap);
>
>   write(trace_fd, buf, n);
> }
>
> void* thread_func(void* /*data*/)
> {
>   pid_t tid = syscall(__NR_gettid);
>   printf("pthread joined. TID %i \n", tid);
>
>   TIME_SPEC ts_next;
>   NANO_TIME wake, init, after_work;
>
>   wake = get_time_ns() + INTERVAL;
>   ts_next = nano2timespec(wake);
>
>   while (true)
>   {
>     init = get_time_ns();
>
>     if (init < wake)
>     {
>       do_work();
>       after_work = get_time_ns();
>
>       const double exec_time = to_us(after_work - init);
>       trace_write("rt_test_exec_time - %f", exec_time);
>     }
>     else
>     {
>       printf("overrun detected\n");
>     }
>
>     clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(ts_next), NULL);
>     wake = wake + INTERVAL;
>     ts_next = nano2timespec(wake);
>   }
>   return NULL;
> }
>
> int main(int /*argc*/, char* /*argv*/[])
> {
>   struct sched_param param;
>   pthread_attr_t attr;
>   pthread_t thread;
>   int ret;
>
>   /* Lock memory */
>   if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
>   {
>     printf("mlockall failed: %m\n");
>     exit(-2);
>   }
>
>   /* Allocate all the memory required by the process */
>   if (!malloc(100 * 1048576))  // 100MB
>   {
>     printf("malloc failed\n");
>     exit(-3);
>   }
>
>   /* Initialize pthread attributes (default values) */
>   ret = pthread_attr_init(&attr);
>   if (ret)
>   {
>     printf("init pthread attributes failed\n");
>     return ret;
>   }
>
>   /* Set a specific stack size  */
>   ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN * 100);
>   if (ret)
>   {
>     printf("pthread setstacksize failed\n");
>     return ret;
>   }
>
>   /* Set scheduler policy and priority of pthread */
>   ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
>   if (ret)
>   {
>     printf("pthread setschedpolicy failed\n");
>     return ret;
>   }
>
>   param.sched_priority = 95;
>   ret = pthread_attr_setschedparam(&attr, &param);
>   if (ret)
>   {
>     printf("pthread setschedparam failed\n");
>     return ret;
>   }
>
>   /* Use scheduling parameters of attr */
>   ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
>   if (ret)
>   {
>     printf("pthread setinheritsched failed\n");
>     return ret;
>   }
>
>   /* Create a pthread with specified attributes */
>   ret = pthread_create(&thread, &attr, thread_func, NULL);
>   if (ret)
>   {
>     printf("create pthread failed\n");
>     return ret;
>   }
>
>   /* Open tracer_marker */
>   trace_fd = open("/tracing/trace_marker", O_WRONLY);
>   if (trace_fd == -1)
>   {
>     printf("trace_marker open failed\n");
>     return ret;
>   }
>
>   system("echo 1 > /tracing/tracing_on");             // enable
> tracing system("echo nop > /tracing/current_tracer");       // reset
> trace system("echo function > /tracing/current_tracer");  // use
> function tracer system("echo 1 > /tracing/events/enable");          //
> enable all events
>
>   /* Join the thread and wait until it is done */
>   ret = pthread_join(thread, NULL);
>   if (ret)
>     printf("join pthread failed: %m\n");
>
>   system("echo 0 > /tracing/tracing_on");     // disable tracing
>   system("echo 0 > /tracing/events/enable");  // disable all events
>
>   return ret;
> }
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-rt-users" in the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Cheers, Gene Heskett
--
"There are four boxes to be used in defense of liberty:
 soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
Genes Web page <http://geneslinuxbox.net:6309/gene>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: AW: Non RT threads impact on RT thread
  2018-05-22 10:20 ` AW: " Lampersperger Andreas
  2018-05-22 11:03   ` Jordan Palacios
@ 2018-05-22 12:56   ` Gene Heskett
  1 sibling, 0 replies; 13+ messages in thread
From: Gene Heskett @ 2018-05-22 12:56 UTC (permalink / raw)
  To: linux-rt-users

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: Text/Plain; charset="utf-8", Size: 8053 bytes --]

On Tuesday 22 May 2018 06:20:25 Lampersperger Andreas wrote:

> Hello Jordan,
>
> IMHO this is because the non-RT Tasks uses the same CPU and therefore
> the same cache. Especially when your CPU has hyperthreading also the
> L1-Cache is shared between RT and non-RT. Try using different CPUs for
> RT and non-RT tasks und disable hyperthreading (in the bios).
>
> @all: When I'm not correct, I would be very pleased if somebody let me
> know about this.
>
> Best regards
> Andreas
>
> -----Ursprüngliche Nachricht-----
> Von: linux-rt-users-owner@vger.kernel.org
> [mailto:linux-rt-users-owner@vger.kernel.org] Im Auftrag von Jordan
> Palacios Gesendet: Dienstag, 22. Mai 2018 12:00
> An: linux-rt-users@vger.kernel.org
> Betreff: Non RT threads impact on RT thread
>
> Hello,
>
> We are currently running a version of the linux kernel (3.18.24) with
> the RT-PREEMPT patch. In our system there are several non RT tasks and
> one RT task. The RT process runs in the FIFO scheduler with 95
> priority and a control loop of 1ms.
>
> We have achieved latencies of about 5us which are perfect for us.
>
> Our issue is that the RT task sometimes misses one of its cycles due
> to an unexpected very long execution time of its control loop. In our
> system this is a critical failure.
>
There is also the kernel argument isolcpus, where in a multicore machine, 
it makes the cpu # passed disappear from the schedulers control, and 
linuxcnc then runs its main realtime stuff on this isolated cpu core.  
And that can be a real help with this.

> We enabled tracing in the kernel and started measuring the execution
> time of the RT thread. The execution time is quite constant (about
> 200us), which random spikes every now and then. Thing is, the less non
> RT tasks running in the system the better the RT task behaves.
>
> We wrote a very simple RT application that does some light work and
> writes its execution time using the trace_marker. Execution time is
> constant but IO intensive stuff, like a stress --io 32 or a hdparm,
> will have and impact on its execution time. This is surprising because
> the test does not any kind of work related to IO. Nor does the RT task
> in our system for that matter.
>
> Our question is: Is this behaviour normal? Why are non RT tasks
> affecting the RT task performance? Is there any other kind of test
> that we could run that would shed some light on this issue?
>
> Thanks in advance.
>
> Jordan.
>
>
>
> #include <limits.h>
> #include <pthread.h>
> #include <sched.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/syscall.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <sstream>
> #include <math.h>
> #include <unistd.h>
> #include <stdarg.h>
>
> typedef long long NANO_TIME;
> typedef struct timespec TIME_SPEC;
>
> static const long int INTERVAL = 1000000LL; // 1ms
>
> static TIME_SPEC nano2timespec(NANO_TIME hrt) {
>   TIME_SPEC timevl;
>   timevl.tv_sec = hrt / 1000000000LL;
>   timevl.tv_nsec = hrt % 1000000000LL;
>   return timevl;
> }
>
> static double to_us(NANO_TIME ns)
> {
>   return static_cast<double>(ns) / 1000.0; }
>
> static NANO_TIME get_time_ns(void)
> {
>   TIME_SPEC tv;
>   clock_gettime(CLOCK_REALTIME, &tv);
>   return NANO_TIME(tv.tv_sec) * 1000000000LL + NANO_TIME(tv.tv_nsec);
> }
>
> static const unsigned int WORK_SIZE = 10000;
>
> void do_work()
> {
>   unsigned int i = 0;
>   double aux = 2;
>
>   // do some stuff to use cpu
>   while (i < WORK_SIZE)
>   {
>     aux = pow(aux, i);
>     ++i;
>   }
> }
>
> int trace_fd = -1;
>
> void trace_write(const char* fmt, ...)
> {
>   va_list ap;
>   char buf[256];
>   int n;
>
>   if (trace_fd < 0)
>     return;
>
>   va_start(ap, fmt);
>   n = vsnprintf(buf, 256, fmt, ap);
>   va_end(ap);
>
>   write(trace_fd, buf, n);
> }
>
> void* thread_func(void* /*data*/)
> {
>   pid_t tid = syscall(__NR_gettid);
>   printf("pthread joined. TID %i \n", tid);
>
>   TIME_SPEC ts_next;
>   NANO_TIME wake, init, after_work;
>
>   wake = get_time_ns() + INTERVAL;
>   ts_next = nano2timespec(wake);
>
>   while (true)
>   {
>     init = get_time_ns();
>
>     if (init < wake)
>     {
>       do_work();
>       after_work = get_time_ns();
>
>       const double exec_time = to_us(after_work - init);
>       trace_write("rt_test_exec_time - %f", exec_time);
>     }
>     else
>     {
>       printf("overrun detected\n");
>     }
>
>     clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(ts_next), NULL);
>     wake = wake + INTERVAL;
>     ts_next = nano2timespec(wake);
>   }
>   return NULL;
> }
>
> int main(int /*argc*/, char* /*argv*/[]) {
>   struct sched_param param;
>   pthread_attr_t attr;
>   pthread_t thread;
>   int ret;
>
>   /* Lock memory */
>   if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
>   {
>     printf("mlockall failed: %m\n");
>     exit(-2);
>   }
>
>   /* Allocate all the memory required by the process */
>   if (!malloc(100 * 1048576))  // 100MB
>   {
>     printf("malloc failed\n");
>     exit(-3);
>   }
>
>   /* Initialize pthread attributes (default values) */
>   ret = pthread_attr_init(&attr);
>   if (ret)
>   {
>     printf("init pthread attributes failed\n");
>     return ret;
>   }
>
>   /* Set a specific stack size  */
>   ret = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN * 100);
>   if (ret)
>   {
>     printf("pthread setstacksize failed\n");
>     return ret;
>   }
>
>   /* Set scheduler policy and priority of pthread */
>   ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
>   if (ret)
>   {
>     printf("pthread setschedpolicy failed\n");
>     return ret;
>   }
>
>   param.sched_priority = 95;
>   ret = pthread_attr_setschedparam(&attr, &param);
>   if (ret)
>   {
>     printf("pthread setschedparam failed\n");
>     return ret;
>   }
>
>   /* Use scheduling parameters of attr */
>   ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
>   if (ret)
>   {
>     printf("pthread setinheritsched failed\n");
>     return ret;
>   }
>
>   /* Create a pthread with specified attributes */
>   ret = pthread_create(&thread, &attr, thread_func, NULL);
>   if (ret)
>   {
>     printf("create pthread failed\n");
>     return ret;
>   }
>
>   /* Open tracer_marker */
>   trace_fd = open("/tracing/trace_marker", O_WRONLY);
>   if (trace_fd == -1)
>   {
>     printf("trace_marker open failed\n");
>     return ret;
>   }
>
>   system("echo 1 > /tracing/tracing_on");             // enable
> tracing system("echo nop > /tracing/current_tracer");       // reset
> trace system("echo function > /tracing/current_tracer");  // use
> function tracer system("echo 1 > /tracing/events/enable");          //
> enable all events
>
>   /* Join the thread and wait until it is done */
>   ret = pthread_join(thread, NULL);
>   if (ret)
>     printf("join pthread failed: %m\n");
>
>   system("echo 0 > /tracing/tracing_on");     // disable tracing
>   system("echo 0 > /tracing/events/enable");  // disable all events
>
>   return ret;
> }
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-rt-users" in the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> ----------------------------------------------------------------------
>-------------------------------- Registergericht: Traunstein / Registry
> Court: HRB 275 - Sitz / Head Office: Traunreut
> Aufsichtsratsvorsitzender / Chairman of Supervisory Board: Rainer
> Burkhard Geschäftsführung / Management Board: Thomas Sesselmann
> (Vorsitzender / Chairman), Hubert Ermer, Michael Grimm, Lutz Rissing
>
> E-Mail Haftungsausschluss / E-Mail Disclaimer:
> http://www.heidenhain.de/disclaimer
> N‹§²æìr¸›yúèšØb²X¬¶Ç§vØ^–)Þº{.nÇ+‰·¥Š{±®Û¬z»"žØ
>^n‡r¡ö¦zË\x1aëh™¨è­Ú&¢ø\x1e
®G«éh®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿ
>ïêäz¹Þ–Šàþf£¢·hšˆ§~ˆmš



-- 
Cheers, Gene Heskett
--
"There are four boxes to be used in defense of liberty:
 soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author)
Genes Web page <http://geneslinuxbox.net:6309/gene>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-22 10:00 Non RT threads impact on RT thread Jordan Palacios
  2018-05-22 10:20 ` AW: " Lampersperger Andreas
  2018-05-22 12:51 ` Gene Heskett
@ 2018-05-22 18:34 ` Julia Cartwright
  2018-05-23 15:43   ` Jordan Palacios
  2 siblings, 1 reply; 13+ messages in thread
From: Julia Cartwright @ 2018-05-22 18:34 UTC (permalink / raw)
  To: Jordan Palacios; +Cc: linux-rt-users

On Tue, May 22, 2018 at 12:00:27PM +0200, Jordan Palacios wrote:
> Hello,

Hello Jordan-

> We are currently running a version of the linux kernel (3.18.24) with
> the RT-PREEMPT patch. In our system there are several non RT tasks and
> one RT task. The RT process runs in the FIFO scheduler with 95
> priority and a control loop of 1ms.
>
> We have achieved latencies of about 5us which are perfect for us.
>
> Our issue is that the RT task sometimes misses one of its cycles due
> to an unexpected very long execution time of its control loop. In our
> system this is a critical failure.
>
> We enabled tracing in the kernel and started measuring the execution
> time of the RT thread. The execution time is quite constant (about
> 200us), which random spikes every now and then. Thing is, the less non
> RT tasks running in the system the better the RT task behaves.
>
> We wrote a very simple RT application that does some light work and
> writes its execution time using the trace_marker. Execution time is
> constant but IO intensive stuff, like a stress --io 32 or a hdparm,
> will have and impact on its execution time. This is surprising because
> the test does not any kind of work related to IO. Nor does the RT task
> in our system for that matter.

You haven't specified anything about your hardware setup, nor any
numbers here showing the magnitude of these latency spikes.  Could you
elaborate?

> Our question is: Is this behaviour normal? Why are non RT tasks
> affecting the RT task performance?  Is there any other kind of test
> that we could run that would shed some light on this issue?

I think it's "normal" that there will be _some_ impact from non-RT
tasks.  Even across CPUs in the case where CPUs share some level of
cache.  The question is what magnitude of impact should be expected.

Another thing you might want to look at is irq_smp_affinity, in the case
where your RT task is still serving interrupts it should not be.

Your test already has some scaffolding for tracing.  Start a run with
tracing enabled and stop tracing once you observe a latency larger than
expected; dump the trace buffer; inspect.

  Julia

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-22 18:34 ` Julia Cartwright
@ 2018-05-23 15:43   ` Jordan Palacios
  2018-05-23 16:07     ` Julia Cartwright
  0 siblings, 1 reply; 13+ messages in thread
From: Jordan Palacios @ 2018-05-23 15:43 UTC (permalink / raw)
  To: Julia Cartwright; +Cc: linux-rt-users

Hello,

Thanks for the answers.

We don't have any nvidia card installed on the system.

We'll try the isolcpus in conjunct with our cpuset setup and we'll
look into the irq_smp_affinity.

These are some of the specs of the system. Let me know if you need
something else that might be relevant.

Active module: Congatec conga-TS77/i7-3612QE
Carrier: Connect Tech CCG008
DDR3L-SODIMM-1600 (8GB)
Crucial MX200 250GB mSATA SSD

I have uploaded one graph with an example of our issue here:
https://i.imgur.com/8KoxzNV.png

In blue the time between cycles and in green the execution time of
each loop. X is in seconds and Y in microseconds. As you can see the
execution time is quite constant until we run some intensive IO tasks.
In this case those spikes are caused by a hdparm -tT /dev/sda. In this
particular instance the spike is no issue since its less than our task
period.

The problem arises when spikes that are particularly nasty make us go
over the 1ms limit, resulting in an overrun. Here is an example:
https://i.imgur.com/77sgj3S.png

Till now we have only used tracing in our example application but we
haven't been able to draw any conclusions. I'll try to obtain a trace
of our main update cycle when one of these spikes happen.

Kind regards,

Jordan.

On 22 May 2018 at 20:34, Julia Cartwright <julia@ni.com> wrote:
> On Tue, May 22, 2018 at 12:00:27PM +0200, Jordan Palacios wrote:
>> Hello,
>
> Hello Jordan-
>
>> We are currently running a version of the linux kernel (3.18.24) with
>> the RT-PREEMPT patch. In our system there are several non RT tasks and
>> one RT task. The RT process runs in the FIFO scheduler with 95
>> priority and a control loop of 1ms.
>>
>> We have achieved latencies of about 5us which are perfect for us.
>>
>> Our issue is that the RT task sometimes misses one of its cycles due
>> to an unexpected very long execution time of its control loop. In our
>> system this is a critical failure.
>>
>> We enabled tracing in the kernel and started measuring the execution
>> time of the RT thread. The execution time is quite constant (about
>> 200us), which random spikes every now and then. Thing is, the less non
>> RT tasks running in the system the better the RT task behaves.
>>
>> We wrote a very simple RT application that does some light work and
>> writes its execution time using the trace_marker. Execution time is
>> constant but IO intensive stuff, like a stress --io 32 or a hdparm,
>> will have and impact on its execution time. This is surprising because
>> the test does not any kind of work related to IO. Nor does the RT task
>> in our system for that matter.
>
> You haven't specified anything about your hardware setup, nor any
> numbers here showing the magnitude of these latency spikes.  Could you
> elaborate?
>
>> Our question is: Is this behaviour normal? Why are non RT tasks
>> affecting the RT task performance?  Is there any other kind of test
>> that we could run that would shed some light on this issue?
>
> I think it's "normal" that there will be _some_ impact from non-RT
> tasks.  Even across CPUs in the case where CPUs share some level of
> cache.  The question is what magnitude of impact should be expected.
>
> Another thing you might want to look at is irq_smp_affinity, in the case
> where your RT task is still serving interrupts it should not be.
>
> Your test already has some scaffolding for tracing.  Start a run with
> tracing enabled and stop tracing once you observe a latency larger than
> expected; dump the trace buffer; inspect.
>
>   Julia

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-23 15:43   ` Jordan Palacios
@ 2018-05-23 16:07     ` Julia Cartwright
  2018-05-23 16:19       ` Jordan Palacios
  0 siblings, 1 reply; 13+ messages in thread
From: Julia Cartwright @ 2018-05-23 16:07 UTC (permalink / raw)
  To: Jordan Palacios; +Cc: linux-rt-users

On Wed, May 23, 2018 at 05:43:57PM +0200, Jordan Palacios wrote:
> Hello,
>
> Thanks for the answers.
>
> We don't have any nvidia card installed on the system.
>
> We'll try the isolcpus in conjunct with our cpuset setup and we'll
> look into the irq_smp_affinity.

Given the spike magnitudes you are seeing, I doubt they are task
migration related; meaning I don't think that isolcpus will make a
difference.

> These are some of the specs of the system. Let me know if you need
> something else that might be relevant.
>
> Active module: Congatec conga-TS77/i7-3612QE
> Carrier: Connect Tech CCG008
> DDR3L-SODIMM-1600 (8GB)
> Crucial MX200 250GB mSATA SSD
>
> I have uploaded one graph with an example of our issue here:
>
> https://i.imgur.com/8KoxzNV.png
>
> In blue the time between cycles and in green the execution time of
> each loop. X is in seconds and Y in microseconds. As you can see the
> execution time is quite constant until we run some intensive IO tasks.
> In this case those spikes are caused by a hdparm -tT /dev/sda. In this
> particular instance the spike is no issue since its less than our task
> period.

Interesting.  Does that 2-second higher-latency window directly coincide
with the starting/stopping of the hdparm load?

> The problem arises when spikes that are particularly nasty make us go
> over the 1ms limit, resulting in an overrun. Here is an example:
>
> https://i.imgur.com/77sgj3S.png
>
> Till now we have only used tracing in our example application but we
> haven't been able to draw any conclusions. I'll try to obtain a trace
> of our main update cycle when one of these spikes happen.

This would be most helpful.  The first step will be to confirm the
assumption that nothing else is executing on the CPU with this RT task.

Also, keep in mind that tracing induces some overhead, so you might need
to adjust your threshold accordingly.  I've found that most of the
latency issues I've debugged can be via the irq, sched, and timer trace
events (maybe syscalls as well) so that's where I typically start.

It may also be worth a test with a later -rt kernel series like 4.14-rt
or even 4.16-rt to see if you can reproduce the issue there.

   Julia

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-23 16:07     ` Julia Cartwright
@ 2018-05-23 16:19       ` Jordan Palacios
  2018-05-25 13:38         ` Jordan Palacios
  0 siblings, 1 reply; 13+ messages in thread
From: Jordan Palacios @ 2018-05-23 16:19 UTC (permalink / raw)
  To: Julia Cartwright; +Cc: linux-rt-users

On 23 May 2018 at 18:07, Julia Cartwright <julia@ni.com> wrote:
> On Wed, May 23, 2018 at 05:43:57PM +0200, Jordan Palacios wrote:
>> Hello,
>>
>> Thanks for the answers.
>>
>> We don't have any nvidia card installed on the system.
>>
>> We'll try the isolcpus in conjunct with our cpuset setup and we'll
>> look into the irq_smp_affinity.
>
> Given the spike magnitudes you are seeing, I doubt they are task
> migration related; meaning I don't think that isolcpus will make a
> difference.
>
>> These are some of the specs of the system. Let me know if you need
>> something else that might be relevant.
>>
>> Active module: Congatec conga-TS77/i7-3612QE
>> Carrier: Connect Tech CCG008
>> DDR3L-SODIMM-1600 (8GB)
>> Crucial MX200 250GB mSATA SSD
>>
>> I have uploaded one graph with an example of our issue here:
>>
>> https://i.imgur.com/8KoxzNV.png
>>
>> In blue the time between cycles and in green the execution time of
>> each loop. X is in seconds and Y in microseconds. As you can see the
>> execution time is quite constant until we run some intensive IO tasks.
>> In this case those spikes are caused by a hdparm -tT /dev/sda. In this
>> particular instance the spike is no issue since its less than our task
>> period.
>
> Interesting.  Does that 2-second higher-latency window directly coincide
> with the starting/stopping of the hdparm load?

Yes. It coincides with the part that tests cache reads to be more precise.

>> The problem arises when spikes that are particularly nasty make us go
>> over the 1ms limit, resulting in an overrun. Here is an example:
>>
>> https://i.imgur.com/77sgj3S.png
>>
>> Till now we have only used tracing in our example application but we
>> haven't been able to draw any conclusions. I'll try to obtain a trace
>> of our main update cycle when one of these spikes happen.
>
> This would be most helpful.  The first step will be to confirm the
> assumption that nothing else is executing on the CPU with this RT task.
>
> Also, keep in mind that tracing induces some overhead, so you might need
> to adjust your threshold accordingly.  I've found that most of the
> latency issues I've debugged can be via the irq, sched, and timer trace
> events (maybe syscalls as well) so that's where I typically start.
>
> It may also be worth a test with a later -rt kernel series like 4.14-rt
> or even 4.16-rt to see if you can reproduce the issue there.
>
>    Julia

Thanks Julia. I'll look into it and report back.

Kind regards.

Jordan.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-23 16:19       ` Jordan Palacios
@ 2018-05-25 13:38         ` Jordan Palacios
  2018-05-25 15:02           ` Julia Cartwright
  0 siblings, 1 reply; 13+ messages in thread
From: Jordan Palacios @ 2018-05-25 13:38 UTC (permalink / raw)
  To: Julia Cartwright; +Cc: linux-rt-users

Hello,

We managed to trace one of the failing cycles. The trace is here:
https://pastebin.com/YJBrSQpJ

It seems our application is relinquishing the cpu (line 411) due to a
sys_futex call (line 350). We still don't understand why though. We
are not very familiar with all the kernel functions.

Kind regards.

Jordan.

On 23 May 2018 at 18:19, Jordan Palacios
<jordan.palacios@pal-robotics.com> wrote:
> On 23 May 2018 at 18:07, Julia Cartwright <julia@ni.com> wrote:
>> On Wed, May 23, 2018 at 05:43:57PM +0200, Jordan Palacios wrote:
>>> Hello,
>>>
>>> Thanks for the answers.
>>>
>>> We don't have any nvidia card installed on the system.
>>>
>>> We'll try the isolcpus in conjunct with our cpuset setup and we'll
>>> look into the irq_smp_affinity.
>>
>> Given the spike magnitudes you are seeing, I doubt they are task
>> migration related; meaning I don't think that isolcpus will make a
>> difference.
>>
>>> These are some of the specs of the system. Let me know if you need
>>> something else that might be relevant.
>>>
>>> Active module: Congatec conga-TS77/i7-3612QE
>>> Carrier: Connect Tech CCG008
>>> DDR3L-SODIMM-1600 (8GB)
>>> Crucial MX200 250GB mSATA SSD
>>>
>>> I have uploaded one graph with an example of our issue here:
>>>
>>> https://i.imgur.com/8KoxzNV.png
>>>
>>> In blue the time between cycles and in green the execution time of
>>> each loop. X is in seconds and Y in microseconds. As you can see the
>>> execution time is quite constant until we run some intensive IO tasks.
>>> In this case those spikes are caused by a hdparm -tT /dev/sda. In this
>>> particular instance the spike is no issue since its less than our task
>>> period.
>>
>> Interesting.  Does that 2-second higher-latency window directly coincide
>> with the starting/stopping of the hdparm load?
>
> Yes. It coincides with the part that tests cache reads to be more precise.
>
>>> The problem arises when spikes that are particularly nasty make us go
>>> over the 1ms limit, resulting in an overrun. Here is an example:
>>>
>>> https://i.imgur.com/77sgj3S.png
>>>
>>> Till now we have only used tracing in our example application but we
>>> haven't been able to draw any conclusions. I'll try to obtain a trace
>>> of our main update cycle when one of these spikes happen.
>>
>> This would be most helpful.  The first step will be to confirm the
>> assumption that nothing else is executing on the CPU with this RT task.
>>
>> Also, keep in mind that tracing induces some overhead, so you might need
>> to adjust your threshold accordingly.  I've found that most of the
>> latency issues I've debugged can be via the irq, sched, and timer trace
>> events (maybe syscalls as well) so that's where I typically start.
>>
>> It may also be worth a test with a later -rt kernel series like 4.14-rt
>> or even 4.16-rt to see if you can reproduce the issue there.
>>
>>    Julia
>
> Thanks Julia. I'll look into it and report back.
>
> Kind regards.
>
> Jordan.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-25 13:38         ` Jordan Palacios
@ 2018-05-25 15:02           ` Julia Cartwright
  2018-05-25 15:45             ` Jordan Palacios
  0 siblings, 1 reply; 13+ messages in thread
From: Julia Cartwright @ 2018-05-25 15:02 UTC (permalink / raw)
  To: Jordan Palacios; +Cc: linux-rt-users

On Fri, May 25, 2018 at 03:38:47PM +0200, Jordan Palacios wrote:
> Hello,
> 
> We managed to trace one of the failing cycles. The trace is here:
>
> https://pastebin.com/YJBrSQpJ
> 
> It seems our application is relinquishing the cpu (line 411) due to a
> sys_futex call (line 350). We still don't understand why though. We
> are not very familiar with all the kernel functions.

You'll see a futex system call whenever there is contention on a
userspace mutex.  In this case, your thread is issuing a FUTEX_WAIT,
which is the futex op used to implement a contended non-PI lock
operation.

An RT task blocking on a non-PI mutex is game over w.r.t. expecting any
bound execution time guarantees.

In other words: the traces show that this is a userspace problem, not a
kernel problem.  Solving this will require you to inspect your
application's locking.

It may be helpful for you, in this effort, to identify the other thread
which eventually issues the FUTEX_WAKE (used for non-PI unlock
operation); the trace you linked only includes traces for CPU3, the
waker is on another CPU.  The remote wakeup occurs at timestamp
12321.992480.

   Julia

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-25 15:02           ` Julia Cartwright
@ 2018-05-25 15:45             ` Jordan Palacios
  2018-05-25 16:26               ` Julia Cartwright
  0 siblings, 1 reply; 13+ messages in thread
From: Jordan Palacios @ 2018-05-25 15:45 UTC (permalink / raw)
  To: Julia Cartwright; +Cc: linux-rt-users

Thanks Julia. You've been of great help.

Quick question. How do you know the wakeup occurs at timestamp 12321.992480?

At that timestamp the only thing we see is:

  <idle>-0     [003] .n..1.. 12321.992480: rcu_idle_exit <-cpu_startup_entry
  <idle>-0     [003] dn..1.. 12321.992480: rcu_eqs_exit_common.isra.46
<-rcu_idle_exit
  <idle>-0     [003] .n..1.. 12321.992480: arch_cpu_idle_exit
<-cpu_startup_entry
  <idle>-0     [003] .n..1.. 12321.992480: atomic_notifier_call_chain
<-arch_cpu_idle_exit

And we also see this:

  tuators_manager-1512  [003] ....1.. 12321.992495: sys_futex(uaddr:
7f41cc000020, op: 81, val: 1, utime: 7f41e4a60f19, uaddr2: 0, val3:
302e332e312e31)

Can you explain us how is it related to the same futex, please? We see
this call repeatedly across all the trace.

We'll try tracing the other threads to pick who issues the FUTEX_WAKE.

Kind regards,
Jordan.

On 25 May 2018 at 17:02, Julia Cartwright <julia@ni.com> wrote:
> On Fri, May 25, 2018 at 03:38:47PM +0200, Jordan Palacios wrote:
>> Hello,
>>
>> We managed to trace one of the failing cycles. The trace is here:
>>
>> https://pastebin.com/YJBrSQpJ
>>
>> It seems our application is relinquishing the cpu (line 411) due to a
>> sys_futex call (line 350). We still don't understand why though. We
>> are not very familiar with all the kernel functions.
>
> You'll see a futex system call whenever there is contention on a
> userspace mutex.  In this case, your thread is issuing a FUTEX_WAIT,
> which is the futex op used to implement a contended non-PI lock
> operation.
>
> An RT task blocking on a non-PI mutex is game over w.r.t. expecting any
> bound execution time guarantees.
>
> In other words: the traces show that this is a userspace problem, not a
> kernel problem.  Solving this will require you to inspect your
> application's locking.
>
> It may be helpful for you, in this effort, to identify the other thread
> which eventually issues the FUTEX_WAKE (used for non-PI unlock
> operation); the trace you linked only includes traces for CPU3, the
> waker is on another CPU.  The remote wakeup occurs at timestamp
> 12321.992480.
>
>    Julia

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Non RT threads impact on RT thread
  2018-05-25 15:45             ` Jordan Palacios
@ 2018-05-25 16:26               ` Julia Cartwright
  0 siblings, 0 replies; 13+ messages in thread
From: Julia Cartwright @ 2018-05-25 16:26 UTC (permalink / raw)
  To: Jordan Palacios; +Cc: linux-rt-users

Hey Jordan-

(Quick administrative note: could you please not top post in your replies?)

On Fri, May 25, 2018 at 05:45:44PM +0200, Jordan Palacios wrote:
> On 25 May 2018 at 17:02, Julia Cartwright <julia@ni.com> wrote:
> > On Fri, May 25, 2018 at 03:38:47PM +0200, Jordan Palacios wrote:
> >> Hello,
> >>
> >> We managed to trace one of the failing cycles. The trace is here:
> >>
> >> https://pastebin.com/YJBrSQpJ
> >>
[..]
> > In other words: the traces show that this is a userspace problem, not a
> > kernel problem.  Solving this will require you to inspect your
> > application's locking.
> >
> > It may be helpful for you, in this effort, to identify the other thread
> > which eventually issues the FUTEX_WAKE (used for non-PI unlock
> > operation); the trace you linked only includes traces for CPU3, the
> > waker is on another CPU.  The remote wakeup occurs at timestamp
> > 12321.992480.
>
> Quick question. How do you know the wakeup occurs at timestamp 12321.992480?

The CPU has gone completely idle in the subsequent traces.

These traces are the first in the exit-from-idle path.  Given that the
CPU then schedules in your task, it's reasonable to assume that this CPU
exitted idle due to a remote wakeup from another CPU.

> At that timestamp the only thing we see is:
>
>   <idle>-0     [003] .n..1.. 12321.992480: rcu_idle_exit <-cpu_startup_entry
>   <idle>-0     [003] dn..1.. 12321.992480: rcu_eqs_exit_common.isra.46 <-rcu_idle_exit
>   <idle>-0     [003] .n..1.. 12321.992480: arch_cpu_idle_exit <-cpu_startup_entry
>   <idle>-0     [003] .n..1.. 12321.992480: atomic_notifier_call_chain <-arch_cpu_idle_exit
>
> And we also see this:
>
>   tuators_manager-1512  [003] ....1.. 12321.992495: sys_futex(uaddr: 7f41cc000020, op: 81, val: 1, utime: 7f41e4a60f19, uaddr2: 0, val3: 302e332e312e31)
>
> Can you explain us how is it related to the same futex, please? We see
> this call repeatedly across all the trace.

This is the same futex, as identified by the uaddr argument, but the
operation is 81, which (according to include/uapi/linux/futex.h is
FUTEX_WAKE | FUTEX_PRIVATE_FLAG).  This is likely an unlock operation.

This makes sense, when you think about it.  Your tuators_manager was
just woken up and completed it's pending FUTEX_WAIT op (it successfully
acquired the lock), then it executed it's critical section, now it's
releasing the lock.  This is why you then see this FUTEX_WAKE.

> We'll try tracing the other threads to pick who issues the FUTEX_WAKE.

Identifying them is just the most obvious and easiest starting point.
You'll need to figure out whether or not it makes sense for your
application to be sharing locks between high priority and low-priority
threads.  If it is necessary, then you will at the very least need to
make use of PI mutexes.

Good luck,
   Julia

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2018-05-25 16:26 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-22 10:00 Non RT threads impact on RT thread Jordan Palacios
2018-05-22 10:20 ` AW: " Lampersperger Andreas
2018-05-22 11:03   ` Jordan Palacios
2018-05-22 12:56   ` AW: " Gene Heskett
2018-05-22 12:51 ` Gene Heskett
2018-05-22 18:34 ` Julia Cartwright
2018-05-23 15:43   ` Jordan Palacios
2018-05-23 16:07     ` Julia Cartwright
2018-05-23 16:19       ` Jordan Palacios
2018-05-25 13:38         ` Jordan Palacios
2018-05-25 15:02           ` Julia Cartwright
2018-05-25 15:45             ` Jordan Palacios
2018-05-25 16:26               ` Julia Cartwright

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.