owned this note
owned this note
Published
Linked with GitHub
# 2016q3 Homework2 (phonebook-concurrent)
contribute by <`andy19950`>
### Refactor
#### 首先先詳讀程式碼,可以發現幾個問題
1. **main.c 裡面使用太多 #ifndef #if defined**
- 其實很多都可以放一起使用,把它們合併起來吧
2. **變數名稱看不懂**
- 許多變數名稱都宣告成 ptr i j 第一次看根本看不懂,把它改成有意義的名字吧!
3. **程式碼指標使用有誤**
- 在 main.c 後面把 linked-list 接起來時少接了每個 linked-list 的 head node
- findName() 裡面一開始也少找了第一個 node ,這些錯誤會讓程式搜尋其他名字的時候壞掉。
4. **額外的宣告**
- 像是 pdtail 之類的多餘的宣告或定義把它拿掉
---
### MMAP
```c
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
```
* `addr` : 要map到的記憶體位置,傳NULL系統會自行尋找一塊空間 mapping 完之後回傳。
* `length`: 要 mapping 的長度,它會從 fd + offset 的位置開始 mapping 檔案。
* `prot`: **不能跟 open mode 有衝突**
- `PROT_EXEC` Pages may be executed.
- `PROT_READ` Pages may be read.
- `PROT_WRITE` Pages may be written.
- `PROT_NONE` Pages may not be accessed.
* `flags`: 選擇 map file 能不能被其他程式看到
* `fd`: 用系統函式 open 打開的檔案位置,open mode 可以選擇檔案的讀寫屬性,不能跟 prot 有衝突。
* `offset`: 從檔案的哪裡開始 mapping,offset 必須是 page size 的倍數,可以用 sysconf(_SC_PAGE_SIZE) 取得。
>>`mmap` 是 UNIX 系統呼叫 [name=jserv]
- 一般來說把資料從硬碟搬進記憶體時,會建立 page table 來紀錄 virtual address 與 physical address 的相對關係,在程式執行時用動態位置轉換來取得實體位置裡面的資料。
- mmap 就有點像是這樣,只是它不把資料搬進記憶體,只將實體位置跟虛擬位置的關係記錄下來,如此可以省去許多 I/O 的時間。
>> 在這份程式碼中,缺乏驗證資料正確性的機制,請嘗試逐一輸出 last name 到一份檔案,再跟 `dictionary/words.txt` 比對。 [name=jserv]
---
### 資料正確性檢查
- 因為我把 append 稍做修改,改成比較像是 insert,所以 linked-list 的順序是完全亂掉的。
- 因此我在 main 的最下面把輸入資料再重新跑一遍,每個名字都去 findName() 確認有沒有在 linked-list 內。
- 時間複雜度是 O(n^2^),因為資料量太龐大了所以驗證一次非常花時間。
```C=
while(fgets(line, sizeof(line), fp)) {
e = pHead;
printf("%s", line);
if(strcmp(findName(line, e)->lastName, line) != 0) {
printf("ERROR : Name %s is not in linked-list!!\n", line);
}
}
```
- 然後我執行 `./phonebook-concurrent > output.txt` 搜尋 `ERROR` 之後找不到就代表 linked-list 內部資料完全正確
:::warning
E486: 找不到 ERROR
:::
- 若要加速驗證時間的話可以寫一個 linked-list sort function 把它排序成跟原來檔案的順序一樣,這樣時間複雜度是 O(nlogn)。
---
### findName() 的缺點
<s>
- 資料都在硬碟裡面,所以不允許修改它的內容,我本來想讓在 findName 找到的時候直接去把 \n 轉成 \0 ,但每次都會 segmentation fault。
</s>
>> `mmap` 可在記憶體映射 (map) 給定檔案時,指定存取模式,請詳細閱讀 man page: [mmap(2)](http://man7.org/linux/man-pages/man2/mmap.2.html) [name=jserv]
>> 謝謝老師,正在想有沒有辦法解決呢!! [name=andy19950]
>> 下面有修改過 findName 的版本所以刪掉的地方就當做沒看到吧 [name=andy19950]
- 後來我發現原本的程式碼是把要找的名字跟 map 裡的資料做比較,找到後就 malloc 一塊記憶體位置把要找的名字寫入。
- 但是如果這支程式長時間的執行,當所有名字都在記憶體內部之後,這隻程式依然會傻傻的一直 malloc 空間給它,所以如果多執行幾次 findName 可能會發生 segmentation fault 。
### 修改 open mode 及 mmap prot
- 我把兩邊的參數都修改成 read write 模式
- 然後我就可以對檔案做修改了!!
```C=
int fd = open(ALIGN_FILE, O_RDWR | O_NONBLOCK);
char *map = mmap(NULL, fs, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
```
#### 於是我可以把 findName 改成可直接把 \n -> \0
- 因為我有修改過變數名稱,看不懂的話可以先去 github 看一下 .h 檔
```C=
while (current != NULL) {
if (strncasecmp(lastName, current->lastName, len) == 0) {
current->lastName[len] = '\0';
current->dtl = (detail *) malloc( sizeof(detail));
return current;
}
current = current->pNext;
}
```
---
### 使用 thread pool -- [source code](https://github.com/mbrossard/threadpool)
```C=
threadpool_t *threadpool_create(int thread_count,
int queue_size,
int flags);
int threadpool_add(threadpool_t *pool,
void (*routine)(void *),
void *arg, int flags);
int threadpool_destroy(threadpool_t *pool, int flags);
```
1. `threadpool_create`:傳入 thread 的數量,queue 的大小,回傳 threadpool 型態是 threadpool_t
2. `threadpool_add`:傳入 threadpool,要執行的function位置,要傳入的參數
3. `threadpool_destroy`:傳入 threadpool,會把 threadpool 的空間 free 掉
:::info
flags 只有 destroy 會用到, threadpool_graceful = 1,其他的傳 NULL 就可以了。
:::
- 我個人覺得用起來跟 pthread 很像
- 程式碼改起來也很像,就是把
- `pthread_create` -> `threadpool_create` + `threadpool_add`
- `pthread_join` -> `threadpool_destroy`
```C=
threadpool_t *pool = threadpool_create(THREAD_NUM, 512, NULL);
for (int i = 0; i < THREAD_NUM; i++) {
threadpool_add(pool, &append, app[i], NULL);
}
threadpool_destroy(pool, 1);
```
#### 執行結果
![](https://i.imgur.com/UgdstMp.png)
- 效果好像不大, ~~THREAD_NUM = 4 是最佳了~~
>> 我們只對 append() 有興趣,可以單獨製圖,然後調整 Y 軸刻度,得以比較不同 thread 數量對效能的影響。讓視覺效果更顯著 [name=jserv]
#### 今天把 THREAD_NUM = 1 ~ 64 跑了一次,竟然是一條 thread 跑最快!!
![](https://i.imgur.com/mRWAA8S.png)
---
Reference
- [mmap](https://read01.com/8G70jy.html)