2

Im trying to get a timestamp in ticks to start a periodic task with reduced jitter. To do that I get the ticks at the start of each second and upon first execution of a task I initialize a timestamp by subtracting the startTicks from the currentTicks. The problem is that this has proven very unreliable as most of the time my first task has a Timestamp of -1 Ticks aka -0.001s. This leads me to believe that the rest of them are also invalid.

void main(){
    clock_t startTicks;           //Ticks at the start of Second;
    time_t StartSeconds, CurrentSeconds;            //
    time(&StartSeconds);
    time(&CurrentSeconds);
    // stuff ListFunctions();
    for(;;){
        if(CurrentSeconds != time(NULL)){     // Groundwork of iteratig over code every second
            startTicks = clock();
            // initializeTasks if they need to be
            // reset Task availability
            time(&CurrentSeconds);             
        }
        for (int Task = 0; Task < 4; ++Task) {    // initialize timestamp on first run
            if(Tasks[Task].StampInitialized == 0){
                Tasks[Task].TimeStamp = clock() - startTicks;
                printf("%d - %d = %d", clock(), startTicks, Tasks[Task].TimeStamp);      
                Tasks[Task].StampInitialized = 1;
            }
            // wait if time stamp hasnt been crossed
            printf("Start Task %d: %.3f; ", Task + 1, 1.0 *(clock() - startTicks) / CLOCKS_PER_SECOND);
            // execute Task
        }
    }
}

The output looks like this:

> 0 - 1 = -1 Start Task 1: 0.000;
> 3 - 1 = 2 Start Task 2: 0.005;
> 8 - 1 = 7 Start Task 3: 0.008;
> 11 - 1 = 10 Start Task 4: 0.012;

CLOCKS_PER_SECOND = 1000 which is true as far as I have tested.

I couldn't find anything that explains clock() in more detail and I have a hard time believeing that it only takes MINUS 1ms to get from the start of the programm through the initialization of 4 Tasks. The initialization is nothing more than the creation of an Array for every task and sorting the content. Although apparently going from TimeStamp initializing to the task-execution (which is only writing into a variable once and 1 if question) takes between 0 and 2ms as represented by the output. I really can't think of anything that might cause this issue except some dumb logic error. However I couldnt find anything and I hope its somthing I can fix and not just weird behavior.

Im sorry if a lot of information is missing, this is my first question on any forum of any kind and english is not my mother tongue. Im open to criticism and any questions.

Thanks in advance.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
Glumanda
  • 21
  • 2
  • I suggest you read `clock()` *once* per iteration and store it in a local variable. – Weather Vane Apr 05 '23 at 13:02
  • 2
    `startTicks` is uninitialized. – KamilCuk Apr 05 '23 at 13:24
  • Good spot: `clock_t startTicks = clock();`. Note that it's [risky printing it with `%d`](https://stackoverflow.com/questions/1083142/what-s-the-correct-way-to-use-printf-to-print-a-clock-t). – Weather Vane Apr 05 '23 at 13:26
  • From [man clock](https://man7.org/linux/man-pages/man3/clock.3.html): "The clock() function returns an approximation of processor time used by the program" and "On several other implementations, the value returned by clock() also includes the times of any children whose status has been collected via wait(2) (or another wait-type call)." Are you sure this is the function you are looking for? – Ruud Helderman Apr 05 '23 at 13:31
  • Reading clock() only once is a good suggestion, i already had a variable setup for it but ignored it for some reason. – Glumanda Apr 05 '23 at 13:44
  • @RuudHelderman What does children mean in this context? Do you mean that there is a high liklyhood that clock() doesnt actually represent the time of my c-program alone? If so, what is your suggestion. – Glumanda Apr 05 '23 at 13:47
  • It looks very appealing. – Glumanda Apr 05 '23 at 13:59

1 Answers1

1

startTicks is uninitialized. Initialize it.

clock_t startTicks = clock();

Overall, I do not understand what is going on in the code. if(CurrentSeconds != time(NULL)){ startTicks = clock(); time(&CurrentSeconds); }, the if looks like it doesn't do anything.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • I initialized it now, and it doesnt return negative ticks anymore, the if you are looking at doesnt do anything on the first second i see that now and i think im gonna restructure it to only let the code run once as soon as the second changes so it doesnt run wild before the first second-transition occurs. – Glumanda Apr 05 '23 at 13:38
  • `only let the code run once as soon as the second changes` I do not understand that part. What is the point of measuring if you are going to wait. Instead, use a clock with lower resolution. On Linux we have `clock_gettime(CLOCK_PROCESS_CPUTIME_ID` – KamilCuk Apr 05 '23 at 13:50
  • The goal is to have multiple tasks with varying Frequency in seconds, each Task should be exactly its Frequency away from its next or last execution. When the program starts I let all tasks run in this second and memorize how long the tasks beforehand took. if that task then gets called again it will be called 50 ticks(example) into the second just like in the first second instead of jumping forward 50 ticks to the start of the second. – Glumanda Apr 05 '23 at 13:55
  • If you want to run something periodically inside a program, typically you would use threads for every periodic thingy. On Linux, we have `timer_create` with `SIGEV_THREAD`. Also, I do not fully follow, `clock()` returns the CPU ticks _consumed by your program_, not real time time. Why would you want run something when _your program has consumed_ some cpu time periodically? Typically, you want to run something each real seconds, irrelevant of other programs running on the system. But this all depends on what platform are you aiming for. – KamilCuk Apr 05 '23 at 14:14
  • I dont want to thread, i do run it every real second or as real as the time.h 1970 standard gets, and as far as I understood clock in combination with CLOCKS_PER_SECOND can be used to calculate a real time smaller than a second somewhat consistently. I need such a thing to start my tasks at the same fraction of a second after the second started every time. – Glumanda Apr 05 '23 at 15:53
  • `clock in combination with CLOCKS_PER_SECOND can be used to calculate a real time smaller than a second somewhat consistently` No. Clock counts processor used _by your program_. It's not real time, unless you are the only program running on your cpu. It is definitely not real time, when something else cpu intensive starts running on your machine. – KamilCuk Apr 05 '23 at 16:44
  • Who would have thought that the basic clock function description isn't entirely accurate, no matter im probably gonna switch to what you and Ruud suggested anyway. – Glumanda Apr 05 '23 at 17:00
  • Any description of `clock()` I am aware of said "returns processor time" , not real time. But anyway, "times" - be it GPS, UTC, timezones, user, sys, real, wall - can be confusing. Before you jump, for measuring time _intervals_, use `clock_gettime(CLOCK_MONOTONIC` on linux. REALTIME is _not_ monotonic. – KamilCuk Apr 05 '23 at 17:39
  • On tutorialspoint.com on "clock()" it says: "To get the number of seconds used by the CPU, you will need to divide by CLOCKS_PER_SEC.". If 'seconds used by CPU' translates to processor time I agree and I was not aware of the distinction between the two. – Glumanda Apr 07 '23 at 16:36