# 2025q1 Homework3 (kxo)
contributed by < `Jeffbla` >
### Implement coroutine
> commit [2ac0bab](https://github.com/JeffBla/kxo/commit/2ac0bab46c10222f65582eaa25b8f3492872a5c0)
使用 `longjmp` 與 `setjmp` 實作。
### 將繪製棋盤搬到 userspace
> commit [0142a21](https://github.com/JeffBla/kxo/commit/0142a21e5860d6e2643e864eba62f20f192388dd)
將 `draw_board` 移到 userspace , kernelspace 只負責紀錄 `table`。當 user 需要繪製, kernel 會將 `table` 資訊傳給 user。
### 原本 kxo 棋盤繪製在核心模式,你應該修改程式碼,使畫面呈現的部分全部在使用者層級,且善用 bitops,降低核心和使用者層級之間的通訊成本,應給予相關量化
> commit [2304e60](https://github.com/JeffBla/kxo/commit/2304e604f381742c7609c5bdd0d66a0f68a5fc6d)
將原本的棋盤從利用 `char` 儲存、處理,變成 `uint32_t` 透過 bitop 縮減運算與傳輸成本。
下面為在 10 秒內的利用 `strace` 的統計資料
```shell
$ sudo timeout 10 strace -c -o trace.log ./xo-user
```
更動前:
```shell
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
30.09 0.281159 9 29250 openat
21.94 0.205021 7 29246 write
19.27 0.180034 3 58494 29246 read
16.91 0.157994 5 29246 clock_nanosleep
11.73 0.109584 3 29248 close
0.05 0.000472 472 1 execve
0.01 0.000083 10 8 mmap
0.00 0.000029 9 3 mprotect
0.00 0.000022 5 4 fstat
0.00 0.000021 5 4 ioctl
0.00 0.000015 15 1 munmap
0.00 0.000014 4 3 brk
0.00 0.000013 3 4 fcntl
0.00 0.000008 4 2 pread64
0.00 0.000007 7 1 1 access
0.00 0.000005 5 1 getrandom
0.00 0.000004 4 1 arch_prctl
0.00 0.000004 4 1 set_tid_address
0.00 0.000004 4 1 prlimit64
0.00 0.000003 3 1 set_robust_list
0.00 0.000003 3 1 rseq
------ ----------- ----------- --------- --------- ----------------
100.00 0.934499 5 175521 29247 total
```
使用 `uint32_t` 作為棋盤:
```shell
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
30.68 0.275396 9 30126 openat
21.64 0.194213 6 30122 write
19.03 0.170831 2 60247 30122 read
16.98 0.152449 5 30123 1 clock_nanosleep
11.64 0.104457 3 30125 close
0.01 0.000067 8 8 mmap
0.01 0.000062 20 3 mprotect
0.00 0.000032 32 1 munmap
0.00 0.000028 7 4 ioctl
0.00 0.000027 6 4 fstat
0.00 0.000020 5 4 fcntl
0.00 0.000016 5 3 brk
0.00 0.000007 3 2 pread64
0.00 0.000007 7 1 set_tid_address
0.00 0.000006 6 1 1 access
0.00 0.000006 6 1 set_robust_list
0.00 0.000006 6 1 getrandom
0.00 0.000005 5 1 arch_prctl
0.00 0.000005 5 1 prlimit64
0.00 0.000005 5 1 rseq
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.897645 4 180780 30124 total
```
乍看之下,更動後的 `read` 系統呼叫從 `58494` 到 `60247` ,整體系統呼叫從 `175521` 增加到 `180780` ,效能變差,但由於監測項目不斷執行,因此實際上這些數值,代表在 10 秒內運行了多少系統呼叫,數值越大,代表程式在相同運行較快。
另外,關注於時間的佔比, `read` 系統呼叫從 `19.27%` 到 `19.03%` 佔比減少意味著改進的效能的提昇,這種效能提昇可以在 `usecs/call` 明顯的發現, `read` 從 3 變成 2 ,少了 1 微秒。
:::danger
對照 Ftrace 的輸出分析。
:::
若用 `perf` 觀察 `cycles` 、 `instructions` 、 `cache-misses` 、 `mem-stores`:
```shell
$ sudo timeout 10 perf record -e \
cycles,instructions,cache-misses,mem-stores ./xo-user
$ sudo perf report
```
| Metric | Before | After |
|-----------------------------|--------|--------|
| cpu_atom/cycles | 1K | 2K |
| cpu_core/cycles | 2K | 2K |
| cpu_atom/instructions | 3K | 4K |
| cpu_core/instructions | 10K | 8K |
| cpu_atom/cache-misses | 517 | 659 |
| cpu_core/cache-misses | 1K | 1K |
| cpu_atom/mem-stores | 3K | 3K |
| cpu_core/mem-stores | 11K | 6K |
根據 `Metric` 表格,整體記憶體的操作從 14K 減少到 9K。