Created
April 9, 2013 01:15
-
-
Save wmealing/5342095 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ------------------------------------------------------------------------- | |
* 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