# 2016q3 Homework1 (phonebook)
contributed by <`tang7526`>
### Reviewed by `aweimeow`
* [git 是否沒有配置好呢?](https://github.com/tang7526/phonebook-1/commit/d0e169179bc4ede8a52a505847c74ffb6372d6e8)
* 應該在 commit message 的地方可以連結到用戶,是不是沒有設置 username, email
* git config --global user.name yourname
* git config --global user.email yourmail
> 我有設定username跟email,因為沒設定的話是沒辦法commit的,至於為什麼它沒有連結到用戶,我也不知道原因,要再試試看。[name=tang7526][time=Thu, Oct 6, 2016 4:14 PM][color=#ff0000]
* commit 感覺應該要分兩次做,因為連結中的 commit msg 是 `reduce data structure`,但是修改的程式碼不只像 message 說的那樣,還實作了搜尋的程式碼,故我認為應該要分開寫下 commit
> 嗯,是我漏掉了。[name=tang7526][time=Thu, Oct 6, 2016 4:16 PM][color=#ff0000]
* (這點單純是我的疑惑) [[2]](https://www.byvoid.com/blog/string-hash-compare) 能做文獻嗎,我覺得它只是 blog 文章 XD
> OK,我將文獻一詞改成參考資料。[name=tang7526][time=Thu, Oct 6, 2016 4:18 PM][color=#ff0000]
## 開發環境
OS:Linux Mint 18 "Sarah" - MATE (64-bit)
Linux Kernel:4.4.0-21-generic
### 系統CPU資訊
要讀取系統cpu資訊,可以使用 lscpu 指令,以下是我的系統的CPU資訊:
```shell
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 2
On-line CPU(s) list: 0,1
Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 23
Stepping: 10
CPU MHz: 1600.000
BogoMIPS: 4787.74
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 3072K
NUMA node0 CPU(s): 0,1
```
---
在執行程式(phonebook_orig 和 phonebook_opt) 前,先清空 cache:
```shell
$ echo 1 | sudo tee /proc/sys/vm/drop_caches
```
## 優化前的執行結果
```shell
$ perf stat -e cache-misses ./phonebook_orig
size of entry : 136 bytes
execution time of append() : 0.085271 sec
execution time of findName() : 0.016910 sec
Performance counter stats for './phonebook_orig':
83,9333 cache-misses
0.140261546 seconds time elapsed
```
## 改進方向(1) - reduce data structure
改寫 struct __PHONE_BOOK_ENTRY 的成員,搬動到新的結構中。
```clike=
typedef struct __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];
struct __DETAIL *pDetail;
struct __PHONE_BOOK_ENTRY *pNext;
} entry;
```
## 優化後的執行結果
```shell
$ perf stat -e cache-misses ./phonebook_opt
size of entry : 32 bytes
execution time of append() : 0.061269 sec
execution time of findName() : 0.005793 sec
Performance counter stats for './phonebook_opt':
4,8396 cache-misses
0.079880126 seconds time elapsed
```
比較優化前和優化後的執行結果,可看到:
1. entry的size從136bytes變成32bytes
2. append和findName的執行時間皆有降低
3. cache-misses從83,9333降到4,8396。
## 使用gnuplot來製圖
```shell
$ make plot
```

## 改進方向(2) - hash function
目的:使用 hash function 來加速查詢。
根據參考資料[1],hash function會將輸入的資料壓縮,使得資料量變小,重新建立一個叫做雜湊值的指紋,雜湊值通常用來代表一個短的隨機字母和數字組成的字串。
hash function有很多種,根據參考資料[2],目前最好的hash function為BKDRHash,參考資料[2]亦將各種hash function的C語言程式碼列了出來,BKDRHash function的程式碼如下:
```clike=
// BKDR Hash Function
unsigned int BKDRHash(char *str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
```
### 參考資料
[1] [雜湊函數-維基百科](https://zh.wikipedia.org/wiki/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8)
[2] [各種字符串Hash函數比較](https://www.byvoid.com/blog/string-hash-compare)
## hash function優化後的執行結果
to be continued...