# 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。