Linux 效能分析工具
===
## Perf
### 安裝 & 設定
[安裝方法](https://hackmd.io/c/rJKbX1pFZ/https%3A%2F%2Fhackmd.io%2Fs%2FB11109rdg)
查看目前的 Kernel config 有沒有啟用 Perf: (下面顯示的是已安裝過的)
```shell
$cat "/boot/config-`uname -r`" | grep "PERF_EVENT"
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_PERF_EVENTS_INTEL_UNCORE=y
CONFIG_PERF_EVENTS_INTEL_RAPL=m
CONFIG_PERF_EVENTS_INTEL_CSTATE=m
# CONFIG_PERF_EVENTS_AMD_POWER is not set
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
```
安裝工具:
```shell
$sudo apt-get install linux-tools-common
```
檢查是否安裝成功:
```
$perf top
```
:::warning
有可能因版本不同而沒安裝成功,這時只需照著它顯示缺乏的套件再一次的安裝即可。
:::
若不是在 root 權限下執行此指令會出現以下錯誤畫面。

指示要我們修改 `/proc/sys/kernel/perf_event_paranoid` 的權限值。
* `2` : 不允許任何量測。但部份用來查看或分析已存在的紀錄的指令仍可使用,如 perf ls、perf report、perf timechart、 perf trace。
* `1` : 不允許 CPU events data。但可以使用 perf stat、perf record 並取得 Kernel profiling data。
* `0` : 不允許 raw tracepoint access。但可以使用 perf stat、perf record 並取得 CPU events data。
* `-1`: 權限全開。
另外,如果要檢測 cache miss event ,需要先取消 kernel pointer 的禁用。
```shell
$sudo sh -c " echo -1 > /proc/sys/kernel/perf_event_paranoid"
$sudo sh -c " echo 0 > /proc/sys/kernel/kptr_restrict"
```
### 效能偵測
針對我們所設計的程式 `example.c` 經由編譯後產生的 object file `example`,若要偵測其效能可輸入以下指令:
```shell
$perf stat --repeat 5 \
-e cache-misses,cache-references,instructions,cycles \
./example
```
* `--repeat <n>`或是`-r <n>` 可以重複執行 n 次該程序,並顯示每個 event 的變化區間。
* `-e` 可以指定要量測的event,若沒有指定的話預設會有10種常用的events,在這我們指定 `cache-misses,cache-references` 和 `instructions,cycles`,而類似這種成對的 event,若同時出現 perf 會很貼心幫你計算比例。
```
Performance counter stats for './perf_stat_cache_miss' (5 runs):
4,416,226 cache-misses # 3.437 % of all cache refs ( +- 0.27% )
128,483,262 cache-references ( +- 0.02% )
2,123,281,496 instructions # 0.65 insns per cycle ( +- 0.02% )
3,281,498,034 cycles ( +- 0.21% )
1.299352302 seconds time elapsed ( +- 0.19% )
```
## 清除 Cache
[手動清除 Linux 記憶體快取](https://medium.com/hungys-blog/clear-linux-memory-cache-manually-90bec95ea003)
### 記憶體使用情況
Linux 提供指令來顯示系統中記憶體的使用情況:
```shell
$free
total used free shared buff/cache available
Mem: 8052900 365692 7327268 64876 359940 7388124
Swap: 11999228 0 11999228
```
指令預設是以`KB` 為單位,我們可以發現現在的 cache 使用了將近 360 MB。
### 清除 Cache
若要評估 cache miss 等問題,要先清空 cache:
```shell
$sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
```
有兩種 cache 種類可被清理。
* `2` : 清除 dentries 與 inodes
* `1` : 清除 pagecache
清完後再用 `free` 查看清除後的 Cache 只剩差不多 290 MB 的記憶體使用量。
```shell
total used free shared buff/cache available
Mem: 8052900 365268 7400464 59528 287168 7394000
Swap: 11999228 0 11999228
```
:::warning
在清除 Cache 之前最好先執行 [sync](http://man.linuxde.net/sync) 指令,讓存在 buffer 中準備寫回記憶體的資料強制寫回記憶體。
:::