diff --git a/Makefile b/Makefile index 1223411..3039791 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,10 @@ CC ?= gcc -CFLAGS_common ?= -Wall -std=gnu99 +CFLAGS_common ?= -Wall -g -std=gnu99 CFLAGS_orig = -O0 CFLAGS_opt = -O0 +CFLAGS_hash = -O0 -EXEC = phonebook_orig phonebook_opt +EXEC = phonebook_orig phonebook_opt phonebook_hash all: $(EXEC) SRCS_common = main.c @@ -15,7 +16,12 @@ phonebook_orig: $(SRCS_common) phonebook_orig.c phonebook_orig.h phonebook_opt: $(SRCS_common) phonebook_opt.c phonebook_opt.h $(CC) $(CFLAGS_common) $(CFLAGS_opt) \ - -DIMPL="\"$@.h\"" -o $@ \ + -DOPT -DIMPL="\"$@.h\"" -o $@ \ + $(SRCS_common) $@.c + +phonebook_hash: $(SRCS_common) phonebook_hash.c phonebook_hash.h + $(CC) $(CFLAGS_common) $(CFLAGS_hash) \ + -DHASH -DIMPL="\"$@.h\"" -o $@ \ $(SRCS_common) $@.c run: $(EXEC) @@ -29,6 +35,9 @@ cache-test: $(EXEC) perf stat --repeat 100 \ -e cache-misses,cache-references,instructions,cycles \ ./phonebook_opt + perf stat --repeat 100 \ + -e cache-misses,cache-references,instructions,cycles \ + ./phonebook_hash output.txt: cache-test calculate ./calculate @@ -42,4 +51,4 @@ calculate: calculate.c .PHONY: clean clean: $(RM) $(EXEC) *.o perf.* \ - calculate orig.txt opt.txt output.txt runtime.png + calculate orig.txt opt.txt hash.txt output.txt runtime.png diff --git a/calculate.c b/calculate.c index 9f2d3ab..81c00c6 100644 --- a/calculate.c +++ b/calculate.c @@ -43,8 +43,31 @@ int main(void) opt_sum_a += opt_a; opt_sum_f += opt_f; } - fprintf(output, "append() %lf %lf\n",orig_sum_a / 100.0, opt_sum_a / 100.0); - fprintf(output, "findName() %lf %lf", orig_sum_f / 100.0, opt_sum_f / 100.0); + + fp = fopen("hash.txt", "r"); + if (!fp) { + fp = fopen("opt.txt", "r"); + if (!fp) { + printf("ERROR opening input file hash1.txt\n"); + exit(0); + } + } + + double hash_sum_a = 0.0, hash_sum_f = 0.0, hash_a, hash_f; + for (i = 0; i < 100; i++) { + if (feof(fp)) { + printf("ERROR: You need 100 datum instead of %d\n", i); + printf("run 'make run' longer to get enough information\n\n"); + exit(0); + } + fscanf(fp, "%s %s %lf %lf\n", append, find,&hash_a, &hash_f); + hash_sum_a += hash_a; + hash_sum_f += hash_f; + } + + + fprintf(output, "append() %lf %lf %lf\n",orig_sum_a / 100.0, opt_sum_a / 100.0, hash_sum_a/100 ); + fprintf(output, "findName() %lf %lf %lf", orig_sum_f / 100.0, opt_sum_f / 100.0, hash_sum_f/100 ); fclose(output); fclose(fp); return 0; diff --git a/main.c b/main.c index e24cb9c..c11995e 100644 --- a/main.c +++ b/main.c @@ -35,14 +35,17 @@ int main(int argc, char *argv[]) printf("cannot open the file\n"); return -1; } +#if defined (HASH) + hashTable *ht = hashTableInitial(); +#endif - /* build the entry */ entry *pHead, *e; pHead = (entry *) malloc(sizeof(entry)); printf("size of entry : %lu bytes\n", sizeof(entry)); e = pHead; e->pNext = NULL; + #if defined(__GNUC__) __builtin___clear_cache((char *) pHead, (char *) pHead + sizeof(entry)); #endif @@ -52,7 +55,16 @@ int main(int argc, char *argv[]) i++; line[i - 1] = '\0'; i = 0; +#if defined (HASH) + append(line,ht); +#else e = append(line, e); +#endif + + + + + } clock_gettime(CLOCK_REALTIME, &end); cpu_time1 = diff_in_second(start, end); @@ -62,28 +74,52 @@ int main(int argc, char *argv[]) e = pHead; + /* the givn last name to find */ char input[MAX_LAST_NAME_SIZE] = "zyxel"; - e = pHead; + // e = pHead; + + +#if defined (HASH) + assert(findName(input, ht) && + "Did you implement findName() in " IMPL "?"); + assert(0 == strcmp(findName(input, ht)->lastName, "zyxel")); +#else assert(findName(input, e) && "Did you implement findName() in " IMPL "?"); assert(0 == strcmp(findName(input, e)->lastName, "zyxel")); +#endif + + + + #if defined(__GNUC__) __builtin___clear_cache((char *) pHead, (char *) pHead + sizeof(entry)); #endif /* compute the execution time */ clock_gettime(CLOCK_REALTIME, &start); + + +#if defined (HASH) + findName(input, ht); +#else findName(input, e); +#endif + + clock_gettime(CLOCK_REALTIME, &end); cpu_time2 = diff_in_second(start, end); FILE *output; #if defined(OPT) output = fopen("opt.txt", "a"); +#elif defined(HASH) + output = fopen("hash.txt","a"); #else output = fopen("orig.txt", "a"); + #endif fprintf(output, "append() findName() %lf %lf\n", cpu_time1, cpu_time2); fclose(output); @@ -91,8 +127,14 @@ int main(int argc, char *argv[]) printf("execution time of append() : %lf sec\n", cpu_time1); printf("execution time of findName() : %lf sec\n", cpu_time2); + + +#if defined(HASH) + freeHashList(ht); +#else if (pHead->pNext) free(pHead->pNext); free(pHead); +#endif return 0; } diff --git a/phonebook_hash.c b/phonebook_hash.c new file mode 100644 index 0000000..a19d6a8 --- /dev/null +++ b/phonebook_hash.c @@ -0,0 +1,73 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "phonebook_hash.h" + +/* FILL YOUR OWN IMPLEMENTATION HERE! */ +entry *findName(char lastname[], hashTable *ht) +{ + /* TODO: implement */ + entry *tmp = NULL; + unsigned int hash = BKDRHash(lastname); + /*findname*/ + while(ht->list[hash]) { + tmp = ht->list[hash]; + if (strcasecmp(lastname, tmp->lastName) == 0) + return tmp; + tmp = tmp->pNext; + } + return NULL; +} + +void append(char lastName[], hashTable *ht) +{ + entry *tmp; + unsigned int hash = BKDRHash(lastName); + tmp = (entry *) malloc(sizeof(entry)); + + tmp->pNext = ht->list[hash]; + strcpy(tmp->lastName, lastName); + ht->list[hash]=tmp; +} + +hashTable *hashTableInitial() +{ + hashTable *ht = NULL; + ht = (hashTable *)malloc(sizeof(hashTable)); + ht->list =(entry **)malloc(sizeof(entry *)*SIZE); + int i =0; + while(i<SIZE) { + ht->list[i] =NULL; + i++; + } + + return ht; +} + +unsigned int BKDRHash(char *str) +{ + unsigned int seed=31; + unsigned int hash=0; + int i = 0; + while(i<strlen(str)) { + hash = hash * seed + *str++ ; + } + + return hash % SIZE; +} + +void freeHashList(hashTable *ht) +{ + for(int i=0; i<SIZE; i++) { + entry *tmp = NULL; + while(ht->list[i]) { + tmp = (ht->list[i])->pNext; + free(ht->list[i]); + ht->list[i] = tmp; + } + } + free(ht); +} + diff --git a/phonebook_hash.h b/phonebook_hash.h new file mode 100644 index 0000000..957f133 --- /dev/null +++ b/phonebook_hash.h @@ -0,0 +1,39 @@ +#ifndef _PHONEBOOK_H +#define _PHONEBOOK_H +#define HASH 1 +#define MAX_LAST_NAME_SIZE 16 +#define SIZE 9971 + +typedef struct __PHONE_BOOK_DETAIL { + char firstName[16]; + char email[16]; + char phone[10]; + char cell[10]; + char addr1[16]; + char addr2[16]; + char city[16]; + char state[2]; + char zip[5]; +} detail; + + + +typedef struct __PHONE_BOOK_ENTRY { + char lastName[MAX_LAST_NAME_SIZE]; + detail *pDetail; + struct __PHONE_BOOK_ENTRY *pNext; +} entry; + + +typedef struct __HASH_TABLE { + entry **list ; +} hashTable; + + + +entry *findName(char lastname[], hashTable *ht); +void append(char lastName[], hashTable *ht); +void freeHashList(hashTable * ht); +hashTable *hashTableInitial(void); +unsigned int BKDRHash(char *str); +#endif diff --git a/phonebook_opt.c b/phonebook_opt.c index ee92dc3..f52775f 100644 --- a/phonebook_opt.c +++ b/phonebook_opt.c @@ -1,15 +1,35 @@ +#include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <ctype.h> #include "phonebook_opt.h" /* FILL YOUR OWN IMPLEMENTATION HERE! */ entry *findName(char lastname[], entry *pHead) { - /* TODO: implement */ + /*original implement */ + + while (pHead != NULL) { + if (strcasecmp(lastname, pHead->lastName) == 0) + return pHead; + pHead = pHead->pNext; + } + return NULL; } entry *append(char lastName[], entry *e) { - return NULL; + /* allocate memory for the new entry and put lastName */ + e->pNext = (entry *) malloc(sizeof(entry)); + e = e->pNext; + strcpy(e->lastName, lastName); + e->pNext = NULL; + + return e; + + + } + diff --git a/phonebook_opt.h b/phonebook_opt.h index f9de825..fa33ded 100644 --- a/phonebook_opt.h +++ b/phonebook_opt.h @@ -1,13 +1,15 @@ #ifndef _PHONEBOOK_H #define _PHONEBOOK_H - #define MAX_LAST_NAME_SIZE 16 /* TODO: After modifying the original version, uncomment the following * line to set OPT properly */ -// #define OPT 1 -typedef struct __PHONE_BOOK_ENTRY { - char lastName[MAX_LAST_NAME_SIZE]; +/*phonebook only search lastname so we reduce the __PHONE_BOOK_ENTRY + *size from 136 byte to 32 byte */ +//#define OPT 1 + + +typedef struct __PHONE_BOOK_DETAIL { char firstName[16]; char email[16]; char phone[10]; @@ -17,6 +19,13 @@ typedef struct __PHONE_BOOK_ENTRY { char city[16]; char state[2]; char zip[5]; +} detail; + + + +typedef struct __PHONE_BOOK_ENTRY { + char lastName[MAX_LAST_NAME_SIZE]; + detail *pDetail; struct __PHONE_BOOK_ENTRY *pNext; } entry; diff --git a/scripts/runtime.gp b/scripts/runtime.gp index 8ad29ca..38dff7c 100644 --- a/scripts/runtime.gp +++ b/scripts/runtime.gp @@ -8,4 +8,7 @@ set output 'runtime.png' plot [:][:0.150]'output.txt' using 2:xtic(1) with histogram title 'original', \ '' using ($0-0.06):($2+0.001):2 with labels title ' ', \ '' using 3:xtic(1) with histogram title 'optimized' , \ -'' using ($0+0.3):($3+0.0015):3 with labels title ' ' +'' using 4:xtic(1) with histogram title 'hash' , \ +'' using ($0+0.3):($3+0.0015):3 with labels title ' ', \ +'' using ($0+0.4):($4+0.0015):4 with labels title ' ' +