Skip to content

Instantly share code, notes, and snippets.

@wmealing
Created April 9, 2013 01:15
Show Gist options
  • Save wmealing/5342095 to your computer and use it in GitHub Desktop.
Save wmealing/5342095 to your computer and use it in GitHub Desktop.
/* -------------------------------------------------------------------------
* Semaphore timing test.
*
* gcc -m64 -g -O3 -lm -o sema-test sema-test.c
*
* Based on schedulertest
* Version 1.
------------------------------------------------------------------------- */
#include <math.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <stdint.h>
#include <math.h>
/* Defaults */
int KLOOPS = 1000;
int spawn_thread_count = 12;
#define PRIORITY 1
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
pthread_mutex_t *thread_mutex; /* Mutex we're going to all spin around */
int thread_num; /* Application-defined thread # */
int64_t time_elapsed;
int64_t min;
int64_t mean;
int64_t max;
int64_t total;
};
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = (struct thread_info *) arg;
int id = tinfo->thread_num;
int loop_iter=0;
time_t time_n;
struct timeval tm_start,tm_end;
unsigned times[KLOOPS * 1000];
long total_time=0;
long minimum_time=0xFFFFFF;
long maximum_time=0;
float mean_time=0;
float standard_deviation=0;
int n = 0;
/* This is the test to run for KLOOPS loops */
for (loop_iter=0;(loop_iter/1000)<KLOOPS;loop_iter++) {
n = 0;
gettimeofday(&tm_start,NULL);
pthread_mutex_lock(tinfo->thread_mutex);
/* Pretend work */
double res = 0;
long i = 0;
while (i <n * 200000) {
i++;
res += sqrt(i);
}
/* end pretend work */
pthread_mutex_unlock(tinfo->thread_mutex);
gettimeofday(&tm_end,NULL);
time_n = ((tm_end.tv_sec * 1000000L)+tm_end.tv_usec)-((tm_start.tv_sec*1000000L)+tm_start.tv_usec);
/*
* Store timings for each iteration to calculate std. dev
* and also keep track of minimum and maximum times
* incase they're useful later
*/
times[loop_iter] = time_n/1000;
total_time += times[loop_iter];
if (times[loop_iter] < minimum_time) {
minimum_time = times[loop_iter];
printf("Setting min time... %d\n", minimum_time);
}
if (times[loop_iter] > maximum_time) {
maximum_time = times[loop_iter];
printf("Setting max time ... %d\n", maximum_time);
}
if ((loop_iter % 1000) == 0) {
printf(".");
}
}
mean_time = total_time / (KLOOPS * 1000);
for(loop_iter=0;loop_iter < (KLOOPS * 1000);loop_iter++)
standard_deviation += (times[loop_iter] - mean_time) * (times[loop_iter] - mean_time);
standard_deviation = sqrtf( standard_deviation / (KLOOPS * 1000) );
/* debugging */
printf("\n\n(TID: %d) Min Time (ms): %ld\n", id, minimum_time);
printf("(TID: %d) Avg. Time (ms): %0.4f\n", id , mean_time);
printf("(TID: %d) Max Time (ms): %ld\n", id, maximum_time);
printf("(TID: %d) Std Dev (ms): %0.4f\n",id, standard_deviation);
/* stuff it in tinfo for use later. */
tinfo->min = minimum_time;
tinfo->max = maximum_time;
tinfo->mean = mean_time;
tinfo->total = total_time;
return (void *) tinfo;
}
int main(int argc, char *argv[])
{
long min_total, max_total, mean_total = 0;
int s, tnum, opt;
struct thread_info *tinfo;
void *res;
int c; /* getopt switch */
while ((c = getopt (argc, argv, "t:l:")) != -1)
switch (c){
case 'l':
KLOOPS = atoi(optarg);
fprintf(stdout,"Running with thread count: %d\n", KLOOPS);
break;
case 't':
spawn_thread_count = atoi(optarg);
fprintf(stdout, "Running with loop count: %d \n", spawn_thread_count);
break;
}
/* Nasty , but not horrible */
int64_t times[spawn_thread_count];
pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Allocate memory for pthread_create() arguments */
tinfo = calloc(spawn_thread_count, sizeof(struct thread_info));
if (tinfo == NULL)
handle_error("calloc");
for (tnum = 0; tnum < spawn_thread_count; tnum++) {
tinfo[tnum].thread_num = tnum + 1;
tinfo[tnum].thread_mutex = &thread_mutex;
/* The pthread_create() call stores the thread ID into
corresponding element of tinfo[] */
s = pthread_create(&tinfo[tnum].thread_id, NULL,
&thread_start, &tinfo[tnum]);
if (s != 0)
handle_error_en(s, "pthread_create");
}
/* Now join with each thread, and log its returned value */
for (tnum = 0; tnum < spawn_thread_count; tnum++) {
s = pthread_join(tinfo[tnum].thread_id, &res);
if (s != 0)
handle_error_en(s, "pthread_join");
struct thread_info *returned_tinfo = (struct thread_info *)res;
times[tnum] = returned_tinfo[tnum].time_elapsed;
/*
printf("Joined with thread %d; returned value was %d\n", tinfo[tnum].thread_num, returned_tinfo->thread_num);
printf("Joined with thread %d; time elapsed was %d\n", tinfo[tnum].thread_num, times[tnum]);
*/
}
/* Build some stats */
for (tnum = 0; tnum < spawn_thread_count; tnum++) {
max_total += tinfo[tnum].max;
mean_total += tinfo[tnum].mean;
min_total += tinfo[tnum].min;
}
printf("Report - across all threads\n\n");
printf("Threads: %d\n", spawn_thread_count);
printf("\t Mean Min Time (ms): %ld\n", min_total / spawn_thread_count);
printf("\t Avg contention Time (ms): %0.4f\n", mean_total / spawn_thread_count);
printf("\t Mean Max Time (ms): %ld\n", max_total / spawn_thread_count);
free(tinfo);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment