contribute by <illusion030
, ryanwang522
, hugikun999
, claaaaassic
, Weinux
>
sysprog2017
#ifdef
#elif
來實作不同的版本,版本越多,程式碼就越難閱讀append()
函式中i
, j
的命名也不優雅,畢竟不只是單單代表著迴圈的次數phonebook_opt.c
裡的 findName()
malloc()
函式呼叫失敗的例外處理findName()
改名為 findLastName()
因為是用 lastName 去 find,改名後比較清楚 function 的功能append()
的 for-loop 改用 while 表示,因為太多變量需要隨著迴圈改變i
,j
改成看得出意思的名稱OO的一個非常重要的特性,其實就是延後 function bind 的時間,一般 source code 通過 compiler 編譯成 executable,程式會有什麼樣的行為在編譯成執行檔的時期就已經決定好,然而如果透過 polymorphism 可以延後到程式執行時才依據收到訊息的物件而做出不同的反應行為。C++ 本身是OO語言,可以利用 Inheritance 和 Overriding 來達到多型的目的。
C 就沒有 Inheritance 和 Overriding 可以使用,因此只能利用別的方法達到多型的目的,參考了這篇的方法,其實就是在 strcut 中利用 pointer 來讓各個 instance 可以共用。類似做成 array ,再將各個版本的 function 放進這個 array。如此就可以在執行時期依據不同的版本選擇不同的反應行為。
__PHONE_BOOK_INFO
來讓外界可以得到 PHONEBOOK 裡的資訊getInfo()
,使用者呼叫後就可以得到 entry 裡的內容lastname
找到的 entry 裡的值__PHONE_BOOK_ENTRY
因為 struct 的內容在 original 版本跟 optimal 的版本中不一樣,所以在 .c 檔裡面給內容__PHONE_BOOK_ENTRY
的內容,所以不能在 main.c 中修改 entry 的值phonebook-concurrent
裡並沒有頻繁的 malloc ,導致看起來也只是把 malloc 換成另一種寫法而已@@。
__PHONE_BOOK_ENTRY
的指標)switch-case
的作用var
空間,就只要執行SRCS_common
,其他實作獨立出來,並且用 $^ 來一次包含要 compile 的檔案$man assert
來看一下定義assert()
裡的值為 false 時,就會呼叫 abort(3)
來中止程式先來看看他有什麼優點
原理部份主要是參考了 強大又好用的list_head結構 在對照 kernel 裡的實際 code(註解很詳細), 去大致了解 list.h
的基本原理
list.h
是 linux #include <linux/list.h>
就可以直接使用,但是會出現編譯錯誤,因為 gcc 的預設 include path 是 /usr/inlcude
,但 list.h 是存放在 /usr/src/linux-headers-x.x.x-xx/linux
裡,才會導致錯誤。list.h
到 user space ,只是裡面也有用到一些其他在 kernel 才有的標頭檔,所以決定自己寫一個。這裡介紹一些常用的 Macro 以及結構定義跟範例
有一點要注意的是,list.h 裡面的各種函式都是預設你的 linked-list 中 head 為空的,也就是說每一條 linked-list 從 pHead->next
才開始放資料
list_head 結構,用來串接自定義結構的指標
list
就可以去取得資料offsetof
(在 stddef.h
裡可以看到)
type
結構裡,成員 member
相對於結構起始位址的偏移量
list_entry
list_head
的指標,回傳該 list_head 所屬於的 type
型態的指標,用來取得存放資料的結構list_for_each
list_entry
連用以取得實際資料,也因此產生了 list_for_each_entry
這個很方便的 macrolist_for_each_entry
pos->id = 132;
講了這麼多,其實是想學習這些方便的 macro 用法去改進 phonebook_opt.c
的 linked-list 實作
根據老師的建議去參考 list.h
的 double linked list 實作,並且新增一個版本來進行比較,結果發現 append()
有些微地變快,find()
稍微便慢,還不太懂為什麼會有這一些微小的差異,還有待研究
程式碼變得更簡潔、更容易讀懂
程式更容易擴充以進行各種不同的測量實驗 e.g.當我們需要新增一個實作方式時我們需要
.c
檔配置記憶體給變數 var
時只要呼叫 allocSpace
的macro,e.g
比較三種方式
實驗方式
三種版本各跑 100 次取平均值
Thread 數 = 4
將 text-align 從 import()
移到 main.c
裡
實驗發現 multi-thread 版本因為要執行 text-align 對齊,導致時間大幅增加,要想辦法降低 text-align 所帶來的成本
而 multi-thread 使用 doubleLinkedList 後的版本在 import()
時有減少,但在 findLastName()
時反而增加了
在想是不是因為 doublell 版本有大量的 function call 所以導致
import()
(也可以說是append()
) 的執行時間增加?
韻華