How to run a command at an average of 5 times per second?

On a GNU system and if you have pv, you could do:

cmd='
   that command | to execute &&
     as shell code'

yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh

The -P20 is to execute at most 20 $cmd at the same time.

-L10 limits the rate to 10 bytes per second, so 5 lines per second.

If your $cmds become two slow and causes the 20 limit to be reached, then xargs will stop reading until one $cmd instance at least returns. pv will still carry on writing to the pipe at the same rate, until the pipe gets full (which on Linux with a default pipe size of 64KiB will take almost 2 hours).

At that point, pv will stop writing. But even then, when xargs resumes reading, pv will try and catch up and send all the lines it should have sent earlier as quickly as possible so as to maintain a 5 lines per second average overall.

What that means is that as long as it's possible with 20 processes to meet that 5 run per second on average requirement, it will do it. However when the limit is reached, the rate at which new processes are started will not be driven by pv's timer but by the rate at which earlier cmd instances return. For instance, if 20 are currently running and have been for 10 seconds, and 10 of them decide to finish all at the same time, then 10 new ones will be started at once.

Example:

$ cmd='date +%T.%N; exec sleep 2'
$ yes | pv -qL10 | xargs -n1 -P20 sh -c "$cmd" sh
09:49:23.347013486
09:49:23.527446830
09:49:23.707591664
09:49:23.888182485
09:49:24.068257018
09:49:24.338570865
09:49:24.518963491
09:49:24.699206647
09:49:24.879722328
09:49:25.149988152
09:49:25.330095169

On average, it will be 5 times per second even if the delay between two runs will not always be exactly 0.2 seconds.

With ksh93 (or with zsh if your sleep command supports fractional seconds):

typeset -F SECONDS=0
n=0; while true; do
  your-command &
  sleep "$((++n * 0.2 - SECONDS))"
done

That puts no bound on the number of concurrent your-commands though.


Simplistically, if your command lasts less than 1 second you can just start 5 commands each second. Obviously, this is very bursty.

while sleep 1
do    for i in {1..5}
      do mycmd &
      done
done

If your command might take more than 1 second and you want to spread out the commands you can try

while :
do    for i in {0..4}
      do  sleep .$((i*2))
          mycmd &
      done
      sleep 1 &
      wait
done

Alternatively, you can have 5 separate loops that run independently, with a 1 second minimum.

for i in {1..5}
do    while :
      do   sleep 1 &
           mycmd &
           wait
      done &
      sleep .2
done

With a C program,

You can for example use a thread which sleeps for 0.2 seconds into a while

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid;

void* doSomeThing() {
    While(1){
         //execute my command
         sleep(0.2)
     } 
}

int main(void)
{
    int i = 0;
    int err;


    err = pthread_create(&(tid), NULL, &doSomeThing, NULL);
    if (err != 0)
        printf("\ncan't create thread :[%s]", strerror(err));
    else
        printf("\n Thread created successfully\n");



    return 0;
}

use it to know how to create a thread : create a thread (this is the link I've used to paste this code)