# 2016q3 Homework1 (phonebook) contributed by <`kevinbird61`> [2015秋季留下的筆記](https://hackpad.com/Embedded-System-Hw2--Kb2ocXebcwO) ## 規劃 - [x]閱讀phonebook程式架構 - 如何搭配makefile做使用 - [x]搭配makefile + script 了解perf & gnuplot使用 - [x]測試第1版本(origin) - [x]測試第2版本(opt - huffman tree,使用字串壓縮) - [ ]改善程式效能 ## About Makefile - Cool part - [IMPL] 利用Makefile裡頭的編譯參數-D[...]來告訴程式此時該include檔案全名 - 這樣就能達到只使用同一個main.c來編譯所有檔案 - `$@`、`$<` - 稱之為自動變數 - $@ = target - $< = 第一個dependency - `%` - 樣式規則 ```shell main: main.o foo1.o foo2.o ${CC} main.o foo1.o ${CFLAGS} ${INC} ${LIB} -o $@ %.o: %.c target.h ${CC} $< ${CFLAGS} ${INC} ${LIB} -lpthread -c ``` 舉個例子來看,在編譯時,target main裡頭需要main.o及foo1.o,此時便到%.o該行去,這時的%便是main,而`$<`就是main.c;而換成foo1.o時,此行的%便成為foo1了,而`$<`此時就是foo1.c ## About Gnuplot - 察看script裡頭的runtime.gp來閱讀gnuplot的指令(配makefile) - 以空白為界,上半部主要為設定值(字體、標題等等),下半部主要為設定位置 ```shell plot [:][:0.150]'output.txt' using 2:xtic(1) with histogram title 'original', \ '' using ($0-0.06):(0):2 with labels title ' ' ``` * plot 後面接的兩個分別為[x scale][y scale]'input filename' * 第1行using後面便是拿input file第二行的資料來繪製長條圖;第2行using後面則是設定數字繪製的位置。 ## Origin Version & Structure optimizing version - 原先使用的全串接linked-list,append()及findName()所花費的時間都很多 - 藉由修改原本structure,把不必要的部份以pointer的方式暫時移出,變得到大幅改善 ## String compression version(Huffman Compression) - 主要是去年沒有做出來,想把他完成,再次實作 - 經過計算words.txt裡頭的字母出現的數量來建Huffman code tree(目前先用手動方式建樹)便可以得到26個英文字母的huffman encode的結果 ```xml A:110 B:000001 C:00001 D:01111 E:100 F:111110 G:11110 H:10101 I:0001 J:11111110 K:001110 L:1110 M:01110 N:0101 O:0100 P:10100 Q:11111111 R:0010 S:0110 T:1011 U:00110 V:0000000 W:0000001 X:11111101 Y:001111 Z:11111100 ``` ![](https://i.imgur.com/6jyK1xt.png) ##### 觀察 - 可以看到藍色為Huffman compression的實作結果 - 其append()的花費時間頂破天際,但在findName()的表現還算可以 ##### 探討 - Huffman compression主要的壓縮方式為: - Step 1:統計所有字元出現次數 - Step 2:依據字元出現數量,來對該字元做一個壓縮的動作 - 例如原本的abccbcc,ax1,bx2,cx4;依據出現愈頻繁,壓縮後的字串愈短來假設,a = 00 , b = 01 , c = 1;原本存取abccbcc的大小需要7個char,也就是7*8 = 56 bits;而壓縮後則可以看到,2x1+2x2+1x4 = 10 bits,相對減少記憶體的需求 - Step 3:有了compression的方式後,再每次appendName()時都需要Huffman壓縮過,並動態配置記憶體給lastName - 每次的appendName都需要查表並多了加上compression的動作,導致append時間大幅上升 - 但是再次壓縮了檔案大小,使得cache-misses的數量下降: - 原始 ```XML Performance counter stats for './phonebook_orig' (100 runs): 942,621 cache-misses # 85.133 % of all cache refs ( +- 0.91% ) 1,107,232 cache-references ( +- 1.01% ) 260,742,129 instructions # 1.40 insns per cycle ( +- 0.02% ) 185,766,505 cycles ( +- 0.52% ) 0.058256961 seconds time elapsed ( +- 2.26% ) ``` - 更改datastructure ```XML Performance counter stats for './phonebook_opt' (100 runs): 120,558 cache-misses # 47.111 % of all cache refs ( +- 1.78% ) 255,901 cache-references ( +- 2.12% ) 244,779,086 instructions # 1.74 insns per cycle ( +- 0.02% ) 140,485,801 cycles ( +- 1.56% ) 0.044147859 seconds time elapsed ( +- 1.82% ) ``` - Huffman compression ```XML Performance counter stats for './phonebook_strcp' (100 runs): 81,212 cache-misses # 49.898 % of all cache refs ( +- 1.82% ) 162,754 cache-references ( +- 2.58% ) 773,720,487 instructions # 2.14 insns per cycle ( +- 0.09% ) 361,496,589 cycles ( +- 1.82% ) 0.111428579 seconds time elapsed ( +- 1.83% ) ``` >「程式輸出的文字訊息」請勿使用圖片表示,請改由文字貼上[name=課程助教] - Step 4:之後findName(),把輸入的Name同樣以Huffman compression過後比對 - 增加繪製cache-misses的script來檢視每次運行產生的cache-misses ![](https://i.imgur.com/6tS2GyW.png) - 順便看到perf輸出於stderr,非stdout,所以除了在command時加上2>&1之外,還可以用perf stat -o <fileName>來輸出,並可再加上 -x <file separator>來處理我要輸出的特定字串資訊,這樣就不需要對直接輸出的格式做負責的處理。 ##### 改進空間 - 由結果看,Huffman compression為優化data structure的方式之一;而如何降低append時所帶來的巨大消耗則是關鍵 - 可以加上Hash function來減少append以及findName時的查找時間 ## Reference - [Makefile Intro](http://tetralet.luna.com.tw/?op=ViewArticle&articleId=185) - Perf & Event ![](http://www.brendangregg.com/perf_events/perf_events_map.png)