2017 q1 homework(phonebook)
===
contributed by <`PerterTing`>
### Reviewed by `king1224`
* 關於 phonebook_opt_hash.c 中的 findName 實作,過程中呼叫了兩次 HashTableGet 來找查目標資料,第一次作為檢查,第二次重新找一次才 return,也就是說今天我打開電話簿要找一個人的號碼,當我找到後心想:「我找到了。」但立馬我將電話簿闔上,從頭再次翻閱找尋才能得到號碼
* 關於 HashTablePut 我覺得寫得很好,寫了一個 struct __HASH_TABLE 對於 hash array 的管理上清楚很多
* 關於 HashTableGet 對於資料的維護,今天 Hashtable 是以指標傳入,即有可能更動到資料庫,你在實作上就做了這件事:
```clike=
while(isSame !=0 && table->e[hashCode]->pNext != NULL) {
table->e[hashCode] = table->e[hashCode]->pNext;
isSame = strcmp(lastName, table->e[hashCode]->lastName);
}
```
* 當你找到不合適的答案時,不斷的將該個 hash entry 的 head 往下推進,可像你在 HashTablePut 中有做到的,在最後將 head 設回該在的位置,或創立一個 tmp 變數往下探索,建議可在不想被更動的參數前加上 const 以確保資料安全
## 開發環境
```shell
Architecture: x86_64
CPU 作業模式: 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
每核心執行緒數:2
每通訊端核心數:2
Socket(s): 1
NUMA 節點: 1
供應商識別號: GenuineIntel
CPU 家族: 6
型號: 61
Model name: Intel(R) Core(TM) i5-5250U CPU @ 1.60GHz
製程: 4
CPU MHz: 1941.699
CPU max MHz: 2700.0000
CPU min MHz: 500.0000
BogoMIPS: 3200.29
虛擬: VT-x
L1d 快取: 32K
L1i 快取: 32K
L2 快取: 256K
L3 快取: 3072K
```
linux kernel:
```
peterting@peterting-MacBookAir:~$ uname -a
Linux peterting-MacBookAir 4.8.0-36-generic
```
## 未優化前
* <big>未優化前運行時間</big>
`peterting@peterting-MacBookAir:~/hw1/phonebook$ ./phonebook_orig`
```
size of entry : 136 bytes
execution time of append() : 0.051368 sec
execution time of findName() : 0.005574 sec
```
* <big>未優化前運行狀況</big>
```
Performance counter stats for './phonebook_orig' (5 runs):
3,436,226 cache-misses # 93.565 % of all cache refs ( +- 0.10% )
3,672,567 cache-references ( +- 0.32% )
262,370,280 instructions # 1.46 insn per cycle ( +- 0.10% )
179,856,008 cycles ( +- 0.24% )
0.070947689 seconds time elapsed ( +- 1.14% )
```
## Optimization 1 Structure
第一次優化打算從structure著手,將除了lastName的資料存到另一個 struct 內,使 cache 內存放之資料都是 find 跟 append 所需要之資料,減少 cache miss 5 之情況發生。
* <big>優化後運行時間</big>
```
size of entry : 32 bytes
execution time of append() : 0.044477 sec
execution time of findName() : 0.002213 sec
```
* <big>優化後運行狀況</big>
```
Performance counter stats for './phonebook_opt' (5 runs):
1,197,064 cache-misses # 73.246 % of all cache refs ( +- 0.14% )
1,634,305 cache-references ( +- 0.61% )
244,447,128 instructions # 1.94 insn per cycle ( +- 0.06% )
125,893,965 cycles ( +- 1.15% )
0.052415026 seconds time elapsed ( +- 4.84% )
https://i.imgur.com/2h9euq5.png
```
* <big>效能對比圖</big>
![](https://i.imgur.com/2h9euq5.png)
由此可看出改變 Structure 是可以改善效能的
>>中英文字間請以空白隔開! 前後都要~
>>[name=課程助教][color=red]
## Optimation 2 Hash
這次要嘗試使用 hash function 來改善效能,而算法選擇 BKDRHash。
再程式碼完成之後,想試試看若給予 Hash Table 不同大小的話差異會有多大,因此試了兩種 array size,分別為 "20001" 和 "400001"
* "20001" 優化後執行時間
```
execution time of append() : 0.287863 sec
execution time of findName() : 0.000000 sec
```
從這裡我們就可以知道 Hash table 可以使 findName() 的時間趨近於零,不過 append() 所花的時間太多,因此試試看增加 Array size
* "20001" 優化後運行狀況
```
Performance counter stats for './phonebook_opt_hash' (5 runs):
5,679,587 cache-misses # 56.973 % of all cache refs ( +- 0.77% )
9,968,911 cache-references ( +- 0.18% )
351,744,117 instructions # 0.44 insn per cycle ( +- 0.01% )
803,512,165 cycles ( +- 0.59% )
0.313026708 seconds time elapsed ( +- 0.80% )
```
* "400001" 優化後執行時間
```
execution time of append() : 0.090783 sec
execution time of findName() : 0.000000 sec
```
* "400001" 優化後執行狀況
```
Performance counter stats for './phonebook_opt_hash' (100 runs):
2,272,194 cache-misses # 63.938 % of all cache refs ( +- 0.21% )
3,553,735 cache-references ( +- 0.11% )
309,229,723 instructions # 1.02 insn per cycle ( +- 0.03% )
302,219,971 cycles ( +- 0.19% )
0.120901158 seconds time elapsed ( +- 0.23% )
```
* <big>效能對比圖</big>
![](https://i.imgur.com/ARTfRoM.png)
>>長條圖檔到數據了[name=課程助教][color=red]
由此可以知道若增大 Hash table 之大小,可以縮短 append() 之時間,使得效能能夠提升(不過所耗時間仍然比其他方法多),當然不能給予太多的空間,使用率大概在 0.75 % 為最好,不過在 cache miss 方面倒是沒有改善。
## 小結:
從這個作業中,學到了 Struct size 減小可以增加 cache 中能放的資料數,使 cache miss 的頻率降低,並且學會如何寫 hash table ,讓資料能夠更快速的被找尋到,還有關於 vim的使用以及設定和很多實用的小工具,像是 perf,因此我覺得收穫良多。不過可能因為背景不是資工,而且之前沒有學過很多東西,因此在這邊會花上很多查找資料和閱讀資料的時間,而同時其他人可能已經完成很多作業了。
我相信再經過一陣子的磨練後一定可以更迅速的上手。
## 參考資料:
[哈希表之bkdrhash算法解析及扩展 ](http://blog.csdn.net/wanglx_/article/details/40400693)
[hash function 觀念和實務](https://hackmd.io/s/HJln3jU_e)
[gnuplot 語法解說和示範](https://hackmd.io/s/Skwp-alOg#)