Google Answers Logo
View Question
 
Q: C code to collect data from the last 5 seconds of a process ( Answered 5 out of 5 stars,   1 Comment )
Question  
Subject: C code to collect data from the last 5 seconds of a process
Category: Computers > Programming
Asked by: noisy-ga
List Price: $10.00
Posted: 08 Nov 2002 14:05 PST
Expires: 08 Dec 2002 14:05 PST
Question ID: 103027
I am writing some C code to collect time series data from an on-going
process that I am sampling at about 35Hz.  While the process could go
on for hours, it’s only the last 5 seconds of data before the process
stops that I am interested in.  What’s the most efficient (least CPU
intensive) way to go about collecting this data, so that whenever the
process stops, I only have the last 5 seconds of data stored?
Answer  
Subject: Re: C code to collect data from the last 5 seconds of a process
Answered By: majortom-ga on 08 Nov 2002 16:54 PST
Rated:5 out of 5 stars
 
Sampling at 35hz (35 samples per second) yields 5x35 = 175 samples
during a 5-second window. For purposes of illustration I will assume
that you are obtaining a single integer sample each time, but of
course the algorithm generalizes to other cases.

Literally speaking, the "least CPU intensive" solution would store
every sample for the entire run of the process into a very large buffer, 
since this then allows the last 5 seconds to be played back trivially;
however you specify that "whenever the process stops, I only have the
last 5 seconds of data stored," so I suspect that you want to avoid
using enormous amounts of memory during the process as well, although
you did not mention memory as a constraint.

The solution is to use a "ring buffer." This simple data structure
allows an array with the capacity for exactly 5 seconds of samples
to always contain the last 5 seconds of activity, while maintaining
excellent performance and using minimum memory. This is a traditional 
strategy, employed in many I/O buffering applications that must
keep up with hardware and cope with limited resources.

Here is C code to do the deed. Naturally I have had
to make reference to a few functions that would be
provided by your specific application, namely:

1. process_continues() should return 'true' immediately
if the process is still taking place, 'false' if it is not.
(This is a good place to put your 1/35th second delay.)

2. get_sample() should, of course, fetch a sample. If you
are not using integer samples, just change the type of
the 'data' array.

3. display_sample() is a stand-in for whatever operation you
wish to perform with each sample at the end. 

If you have any questions or concerns, please feel very free
to request clarification!

Thanks for the opportunity to answer your question.


* * * * * * CUT HERE * * * * * *

/* Determine the total samples needed to represent 5 seconds */
#define SECONDS 5
#define HERTZ 35
#define SAMPLES ((SECONDS) * (HERTZ))

/* Declare the sample data array */
int data[SAMPLES];

/* Position of the next sample to be read back from the buffer */
int readPos;

/* Position of the next sample to be written to the buffer */
int writePos = 0;

/* Total samples written; primarily here to keep an eye out for
  the possibility that the buffer has not been filled completely once
  (a very short process!) */
int total = 0;

/* Now carry out the process and obtain samples */
while (process_continues()) {
  data[writePos++] = get_sample();
  total++;
  /* Divide by SAMPLES and take the remainder to determine the next
    writing position. The ring buffer is filled from 0 to SAMPLES - 1,
    and writing then begins again at 0 */
  writePos %= SAMPLES;
}

/* Now the process is done. Time to read the information. */

/* If at least 5 seconds have elapsed, then the entire buffer
  is full, and the oldest sample will be found where the next
  sample would have been written. Otherwise, the oldest sample
  is sample 0, because we have not overwritten any existing
  samples yet */
if (total >= SAMPLES) {
  readPos = writePos;
} else {
  readPos = 0;
} 


/* Special case: no samples (zero-length process). 
  Exit program (you may prefer to return from a function,
  etc) */
if (total == 0) {
  exit(0);
}

/* "Display" the samples from the ring buffer,
  in correct chronological order. The display_sample function 
  is a stand-in for whatever operation you wish to perform with them. */

do {
  display_sample(data[readPos++]);
  /* As before we divide by SAMPLES and take the remainder.
    This allows reading to "wrap around" to the beginning of
    the buffer */
  readPos %= SAMPLES;
} while (readPos != writePos);

/* END OF PROGRAM */
noisy-ga rated this answer:5 out of 5 stars
This answer was just what I was looking for, and the illustrative code
that was included was very helpful.  The comment by opedroso-ga was
also valuable in helping me understand better how a ring buffer works.

Comments  
Subject: Re: C code to collect data from the last 5 seconds of a process
From: opedroso-ga on 09 Nov 2002 16:57 PST
 
Strictly speaking, using the module operator "%=" implies doing a
division and using the remainder for every sample. For a less CPU
intensive approach, I would calculate the number of samples needed (as
already done) and reset the counter each time it is reached:
/* Now carry out the process and obtain samples */ 
while (process_continues()) { 
  data[writePos++] = get_sample(); 
  total++; 
  /* Divide by SAMPLES and take the remainder to determine the next 
    writing position. The ring buffer is filled from 0 to SAMPLES - 1,
    and writing then begins again at 0 */ 
  //replace  writePos %= SAMPLES; with the following couple of lines
  if (writePos >= SAMPLES) 
     writePos = 0;
} 
That way, no division takes place, since even on some older Pentium
Classic an integer division may take over 80 clock cycles.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy