The function displayTimeDifference is not working properly; the issue is that the printf statement is failing. After Googling the format of the printf statement when using a timeval is correct. Not sure why I can't print out the value of the timeval. I'm not getting any system errors from gettimeofday().
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
struct timeval *timeBefore;
struct timeval *timeAfter;
char * Buffer;
double malloctest(const int, const int, const int);
double calloctest(const int, const int, const int);
double allocatest(const int, const int, const int);
void displayTimeDifference();
int main(int argc, char **argv)
{
malloctest(3072, 10, 10);
return 0;
}
double malloctest(const int objectsize, const int numobjects, const int numtests)
{
int i;
int retVal;
for (i = 1; i < numtests; i++) {
if ((retVal = gettimeofday(timeBefore, NULL)) != 0) {
printf("ERROR: gettimeofday failed with code: %d\n", retVal);
}
Buffer = (char*)malloc(objectsize * sizeof(char));
if ((retVal = gettimeofday(timeAfter, NULL)) != 0) {
printf("ERROR: gettimeofday failed with code: %d\n", retVal);
}
displayTimeDifference();
}
return 0.0;
}
void displayTimeDifference()
{
printf("Time in microseconds: %ld microseconds\n", (timeAfter->tv_sec - timeBefore->tv_sec));
}
gettimeofday needs a valid pointer to struct timeval, where it can save the informations, you call it with a NULL pointer.
you should change
struct timeval *timeBefore;
struct timeval *timeAfter;
to
struct timeval timeBefore;
struct timeval timeAfter;
and the calls to gettimeofday(&timeBefore, NULL) and gettimeofday(&timeAfter, NULL). You check the return value of this function and print something, but your program continues as it was successfully.
Also
printf("Time in microseconds: %ld microseconds\n", (timeAfter->tv_sec - timeBefore->tv_sec));
to
printf("Time in seconds: %ld microseconds\n", (timeAfter.tv_sec - timeBefore.tv_sec));.
You are only calculating the seconds, not the microseconds.
Another possibility is to malloc the memory for the pointer, but that is not really necessary.
As already said in another answer you have wrongly declared the struct timeval as pointers.
I share my timing macros:
#define START_TIMER(begin) gettimeofday(&begin, NULL) // ;
#define END_TIMER(end) gettimeofday(&end, NULL) // ;
//get the total number of sec:
#define ELAPSED_TIME(elapsed, begin, end) \
elapsed = (end.tv_sec - begin.tv_sec) \
+ ((end.tv_usec - begin.tv_usec)/1000000.0) // ;
Where you have to define the variables:
struct timeval begin, end;
double elapsed;
Related
Assume I have a function calc_sum() and I want to measure its execution time. I have a callback function info_callback() which prints a message and calculates execution time, it takes void pointer as parameter. I want to cast void* to struct timeval * to retrieve start/end of execution time and calculate the difference, but I can't understand how to pass the pointer to array struct timeval * so that I can access its elements from within info_callback() function.
Whatever I try, I get segmentation fault...
How should I pass and cast pointers to get it work?
EDIT: fixed error in code as Andy Schweig suggested
#include <stdio.h>
#include <sys/time.h>
void calc_sum(int a, int b)
{
int k = a + b;
printf("sum = %d\n", k);
}
void info_callback(const char *msg, void *client_data)
{
struct timeval *t = (struct timeval *) client_data;
double time = (t[1].tv_sec - t[0].tv_sec) * 1000.0; // !!!SEGMENTATION FAULT!!!
time += (t[1].tv_usec - t[0].tv_usec) / 1000.0; //
printf("[TIME] %s: %f, ms", msg, time);
}
int main(int argc, char *argv[])
{
struct timeval t1, t2;
gettimeofday(&t1, NULL);
calc_sum(2, 3);
gettimeofday(&t2, NULL);
struct timeval * tr = (struct timeval*) malloc(2 * sizeof(struct timeval));
tr[0] = t1;
tr[1] = t2;
double time = (tr[1].tv_sec - tr[0].tv_sec) * 1000.0; // sec to ms
time += (tr[1].tv_usec - tr[0].tv_usec) / 1000.0; // us to ms
printf("time = %f, ms\n", time);
info_callback("Execution time", tr);
free(tr);
}
You should pass tr to info_callback instead of &tr. tr points to the array you allocated; &tr is a pointer to the pointer tr.
By the way, any particular reason for using void * instead of the actual type? If you had used the actual type, the compiler would have flagged this.
The result that is printed is always zero (0.00) and I want to know what I am doing wrong.
The first function returns the beginning time and the second the final time.
#include <sys/time.h>
#include <time.h>
void getTime(struct timeval begin){
gettimeofday(&(begin), (struct timezone*) 0);
}
float elapTime(struct timeval begin, struct timeval end){
return (1e+6*((end).tv_sec - (begin).tv_sec) + ((end).tv_usec - (begin).tv_usec));
}
int main(int argc, char **argv) {
struct timeval begin, end;
getTime(begin);
printf("Time: %.2f", elapTime(begin, end));
}
You could do something like this instead:
#include <time.h>
#include <stdio.h>
int main() {
clock_t begin, end;
int i = 1e8;
begin = clock();
while(i--);
end = clock();
printf("Time: %.2f\n", (double) (end-begin)/CLOCKS_PER_SEC);
}
The clock() function counts processor clock cycles. By dividing it by CLOCKS_PER_SEC you get seconds. The code above counts the time it takes to iterate 1e8 down to 0.
Try using more simple functions:
double floattime (void)
{
struct timeval t;
if (gettimeofday (&t, (struct timezone *)NULL) == 0)
return (double)t.tv_sec + t.tv_usec * 0.000001;
return (0);
}
int main(int argc, char **argv) {
double begin;
begin = floattime();
getchar ();
printf("Time: %.2f", floattime () - begin);
return 0;
}
And don't forget to wait some time before calculating time execution. Else, it will always return 0.00s.
I'm trying to develop a program in C that will generate a given number of random integers. It is supposed to use a given number of threads to speed this up. I found out that the regular random function won't work with threads and am now using random_r instead. I keep getting a SegFault at the initstate_r function, which doesn't make sense because I'm trying to initialize variables, not access them. Can anyone tell me what I'm doing wrong here? (The initstate_r function needs to stay in the generateRandomNumbers function.)
Here is the code:
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h> // must include stdio for pvm3.h to compile correctly
#include <sys/times.h> /* for times system call */
#include <sys/time.h> /* for gettimeofday system call */
#include <pthread.h>
/*#define DEBUG 1*/
#define RANDOM_SEED 12345678
//The main work routine
//void generateRandomNumbers(long long);
void *generateRandomNumbers(void *);
double getMilliSeconds();
/* The main work routine */
//void generateRandomNumbers(long long int count)
void *generateRandomNumbers(void *arg)
{
struct random_data buf;
int32_t result;
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
printf("hold 2\n");
long long int* count = (long long int*) arg;
//printf("Count for thread ID# %ld is %lld\n", pthread_self(), *count);
long long int i;
//long int x;
srandom_r(RANDOM_SEED, &buf);
for (i = 0; i < *count; i++) {
random_r(&buf, &result);
#ifdef DEBUG
printf("%ld\n", result);
#endif
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
long long int count, newCount;
int numThreads;
//pthread_t *tids;
double timeStart = 0;
double timeElapsed = 0;
if (argc < 3) {
fprintf(stderr, "Usage: %s <n>\n" ,argv[0]);
exit(1);
}
sscanf(argv[1],"%lld",&count); /* lld for long long int */
sscanf(argv[2],"%d",&numThreads);
pthread_t tids[numThreads];
newCount = count/numThreads;
timeStart = getMilliSeconds(); //And we are off
int i;
for (i=0; i<numThreads; i++)
{
pthread_create(&tids[i], NULL, generateRandomNumbers, (void *) &newCount);
//pthread_join(tids[i], NULL);
}
int j;
for (j=0; j<numThreads; j++)
{
pthread_join(tids[j], NULL);
}
//generateRandomNumbers(count);
printf("generated %lld random numbers\n", count);
timeElapsed = getMilliSeconds() - timeStart;
printf("Elapsed time: %lf seconds\n",(double)(timeElapsed/1000.0));
fflush(stdout);
exit(0);
}
The problem is, initstate_r's second param is supposed to be a char*,
You do:
char rand_statebuf;
printf("hold 1\n");
// This is the function that gives me a SegFault
initstate_r(RANDOM_SEED, &rand_statebuf, 128, &buf);
You pass it a pointer to 1 character which meets the requirement for a character pointer, however you need much more space than just one character. It should be:
char rand_statebuf[128];
initstate_r(RANDOM_SEED,rand_statebuf,sizeof(rand_statebuf),&buf);
How to format struct timespec to string? This structure is returned e.g. by clock_gettime() on Linux gcc:
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
One way to format it is:
printf("%lld.%.9ld", (long long)ts.tv_sec, ts.tv_nsec);
I wanted to ask the same question. Here is my current solution to obtain a string like this: 2013-02-07 09:24:40.749355372
I am not sure if there is a more straight forward solution than this, but at least the string format is freely configurable with this approach.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define NANO 1000000000L
// buf needs to store 30 characters
int timespec2str(char *buf, uint len, struct timespec *ts) {
int ret;
struct tm t;
tzset();
if (localtime_r(&(ts->tv_sec), &t) == NULL)
return 1;
ret = strftime(buf, len, "%F %T", &t);
if (ret == 0)
return 2;
len -= ret - 1;
ret = snprintf(&buf[strlen(buf)], len, ".%09ld", ts->tv_nsec);
if (ret >= len)
return 3;
return 0;
}
int main(int argc, char **argv) {
clockid_t clk_id = CLOCK_REALTIME;
const uint TIME_FMT = strlen("2012-12-31 12:59:59.123456789") + 1;
char timestr[TIME_FMT];
struct timespec ts, res;
clock_getres(clk_id, &res);
clock_gettime(clk_id, &ts);
if (timespec2str(timestr, sizeof(timestr), &ts) != 0) {
printf("timespec2str failed!\n");
return EXIT_FAILURE;
} else {
unsigned long resol = res.tv_sec * NANO + res.tv_nsec;
printf("CLOCK_REALTIME: res=%ld ns, time=%s\n", resol, timestr);
return EXIT_SUCCESS;
}
}
output:
gcc mwe.c -lrt
$ ./a.out
CLOCK_REALTIME: res=1 ns, time=2013-02-07 13:41:17.994326501
The following will return an ISO8601 and RFC3339-compliant UTC timestamp, including nanoseconds.
It uses strftime(), which works with struct timespec just as well as with struct timeval because all it cares about is the number of seconds, which both provide. Nanoseconds are then appended (careful to pad with zeros!) as well as the UTC suffix 'Z'.
Example output: 2021-01-19T04:50:01.435561072Z
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int utc_system_timestamp(char[]);
int main(void) {
char buf[31];
utc_system_timestamp(buf);
printf("%s\n", buf);
}
// Allocate exactly 31 bytes for buf
int utc_system_timestamp(char buf[]) {
const int bufsize = 31;
const int tmpsize = 21;
struct timespec now;
struct tm tm;
int retval = clock_gettime(CLOCK_REALTIME, &now);
gmtime_r(&now.tv_sec, &tm);
strftime(buf, tmpsize, "%Y-%m-%dT%H:%M:%S.", &tm);
sprintf(buf + tmpsize -1, "%09luZ", now.tv_nsec);
return retval;
}
GCC command line example (note the -lrt):
gcc foo.c -o foo -lrt
You can pass the tv_sec parameter to some of the formatting function. Have a look at gmtime, localtime(). Then look at snprintf.
You could use a std::stringstream. You can stream anything into it:
std::stringstream stream;
stream << 5.7;
stream << foo.bar;
std::string s = stream.str();
That should be a quite general approach. (Works only for C++, but you asked the question for this language too.)
Could you please help me how to format a struct timeval instance to human readable format like "2010-01-01 15:35:10.0001"?
You need to manually append the microseconds part, since it's not in the struct tm that strftime() deals with. Here's a snippet:
struct timeval tv;
time_t nowtime;
struct tm *nowtm;
char tmbuf[64], buf[64];
gettimeofday(&tv, NULL);
nowtime = tv.tv_sec;
nowtm = localtime(&nowtime);
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, tv.tv_usec);
Note how we use explicit precision of 06 to get a zero-filled microseconds field. Since the microseconds go from 0 to 999,999, it must always be padded to 6 digits. We don't want to misrepresent e.g. 57 microseconds as 570,000 (compare "1.57" vs "1.000057").
Convert the tv_sec using localtime, and strftime, then append tv_usec part.
Combining previous answers and comments, changing the format to be RFC3339-compliant, and checking all of the error conditions, you get this:
#include <stdio.h>
#include <sys/time.h>
ssize_t format_timeval(struct timeval *tv, char *buf, size_t sz)
{
ssize_t written = -1;
struct tm *gm = gmtime(&tv->tv_sec);
if (gm)
{
written = (ssize_t)strftime(buf, sz, "%Y-%m-%dT%H:%M:%S", gm);
if ((written > 0) && ((size_t)written < sz))
{
int w = snprintf(buf+written, sz-(size_t)written, ".%06dZ", tv->tv_usec);
written = (w > 0) ? written + w : -1;
}
}
return written;
}
int main() {
struct timeval tv;
char buf[28];
if (gettimeofday(&tv, NULL) != 0) {
perror("gettimeofday");
return 1;
}
if (format_timeval(&tv, buf, sizeof(buf)) > 0) {
printf("%s\n", buf);
// sample output:
// 2015-05-09T04:18:42.514551Z
}
return 0;
}
ctime((const time_t *) &timeval.ts.tv_sec)
I think you are looking for this code, just for your reference.
You can use the strftime function to convert a date and time to a string.
Convert the tv_sec using localtime_s instead of localtime, because if you are writing a global function it may cause some problems.
if your function may work in a multi-threaded solution then please consider using localtime_r
This is what I use:
#include <time.h>
#include <string.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#define gmtime_r(ptime,ptm) (gmtime_s((ptm),(ptime)), (ptm))
#else
#include <sys/time.h>
#endif
#define ISO8601_LEN (sizeof "1970-01-01T23:59:59.123456Z")
char *timeval_to_str(char iso8601[restrict static ISO8601_LEN], unsigned precision, const struct timeval * restrict tv) {
struct tm tm;
if (!gmtime_r(&tv->tv_sec, &tm))
return memcpy(iso8601, "Error: Year overflow", sizeof "Error: Year overflow");
tm.tm_year %= 10*1000;
char *frac = iso8601 + strftime(iso8601, sizeof "1970-01-01T23:59:59.", "%Y-%m-%dT%H:%M:%SZ", &tm);
if (precision) {
unsigned long usecs = tv->tv_usec;
for (int i = precision; i < 6; i++) usecs /= 10;
char *spaces = frac + sprintf(frac - 1, ".%-*luZ", precision, usecs) - 3;
if (spaces > frac) while (*spaces == ' ') *spaces-- = '0';
}
return iso8601;
}
precision specifies the width of the seconds fraction. Code is y10k- and yINT_MAX-proof.