# 2018q3 Homework3 (dict)
contributed by < [`p61402`](https://github.com/p61402) >
###### tags: `sysprog`
## 視覺化效能分析
### 觀察`script`資料夾中的`.gp`檔
- `runtime.gp`:看起來需要`output.txt`來繪圖
```gnuplot=
reset
set ylabel 'time(sec)'
set style fill solid
set key center top
set title 'perfomance comparison'
set term png enhanced font 'Verdana,10'
set output 'runtime.png'
plot [:][y=0:0.250]'output.txt' using 2:xtic(1) with histogram title 'cpy', \
'' using 3:xtic(1) with histogram title 'ref' , \
'' using ($0-0.500):(0.110):2 with labels title ' ' textcolor lt 1, \
'' using ($0-0.500):(0.120):3 with labels title ' ' textcolor lt 2,
```
- `runtime3.gp`:需要`bench_cpy.txt`
```guuplot=
reset
set xlabel 'prefix'
set ylabel 'time(sec)'
set title 'perfomance comparison'
set term png enhanced font 'Verdana,10'
set output 'runtime3.png'
set format x "%10.0f"
set xtic 1200
set xtics rotate by 45 right
plot [:12500][:1000]'bench_cpy.txt' using 1:2 with points title 'cpy',\
```
- `runtimebox.gp`:顯示一些統計的數據
```gnuplot=
stats "bench_ref.txt" using 2
stats "bench_cpy.txt" using 2
```
- `runtimept.gp`:使用`bench_cpy.txt`
```gnuplot=
reset
set xlabel 'prefix'
set ylabel 'time(sec)'
set title 'perfomance comparison'
set term png enhanced font 'Verdana,10'
set output 'runtime2.png'
set format x "%10.0f"
set xtic 1200
set xtics rotate by 45 right
plot [:12500][:1000]'bench_cpy.txt' using 1:2 with points title 'cpy',\
'bench_ref.txt' using 1:2 with points title 'ref',\
```
個人覺得檔名取得有些不知所以然,讓人不太能夠理解用處如何。
無論如何,看起來需要以上三個檔案來進行繪圖。
首先是`bench_ref.txt`以及`bench_cpy.txt`,比對`test_ref.c`以及`test_cpy.c`發現前者相對於後者少了下列這一段程式碼:
```c=
if (argc == 2 && strcmp(argv[1], "--bench") == 0) {
int stat = bench_test(root, BENCH_TEST_FILE, LMAX);
tst_free_all(root);
return stat;
}
FILE *output;
output = fopen("cpy.txt", "a");
if (output != NULL) {
fprintf(output, "%.6f\n", t2 - t1);
fclose(output);
} else
printf("open file error\n");
```
因此稍微改動一下將以下程式碼加入`test_ref.c`:
```c=
if (argc == 2 && strcmp(argv[1], "--bench") == 0) {
int stat = bench_test(root, BENCH_TEST_FILE, LMAX);
tst_free(root);
return stat;
}
FILE *output;
output = fopen("ref.txt", "a");
if (output != NULL) {
fprintf(output, "%.6f\n", t2 - t1);
fclose(output);
} else
printf("open file error\n");
```
### Makefile 改動
`output.txt`由`calculate.c`產生,而`calculate.c`需要`ref.txt`以及`cpy.txt`這兩個檔案,這兩個檔案由`test_ref.c`及`test_cpy.c`產生。
`test`的部分可以對`cpy`以及`ref`兩種方法執行 100 次的過程進行效能分析:
```makefile
test: $(TESTS)
echo 3 | sudo tee /proc/sys/vm/drop_caches;
perf stat --repeat 100 \
-e cache-misses,cache-references,instructions,cycles \
./test_cpy --bench $(TEST_DATA)
perf stat --repeat 100 \
-e cache-misses,cache-references,instructions,cycles \
./test_ref --bench $(TEST_DATA)
```
`$ make test` 後出現以下錯誤:
```bash
Error:
You may not have permission to collect stats.
Consider tweaking /proc/sys/kernel/perf_event_paranoid,
which controls use of the performance events system by
unprivileged users (without CAP_SYS_ADMIN).
The current value is 3:
-1: Allow use of (almost) all events by all users
Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
>= 0: Disallow ftrace function tracepoint by users without CAP_SYS_ADMIN
Disallow raw tracepoint access by users without CAP_SYS_ADMIN
>= 1: Disallow CPU event access by users without CAP_SYS_ADMIN
>= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN
To make this setting permanent, edit /etc/sysctl.conf too, e.g.:
kernel.perf_event_paranoid = -1
```
看一下目前的權限:
```bash
$ cat /proc/sys/kernel/perf_event_paranoid
3
```
表示`perf`沒有權限可以執行,直接權限全開設為`-1`了:
```bash
$ sudo sh -c " echo -1 > /proc/sys/kernel/perf_event_paranoid"
```
成功權限全開:
```bash
$ cat /proc/sys/kernel/perf_event_paranoid
-1
```
將程式碼中冗余的`printf`註解掉後,重新`$ make test`後得到以下結果:
```bash
Performance counter stats for './test_cpy --bench s Tai' (100 runs):
1,021,598 cache-misses # 44.429 % of all cache refs ( +- 0.15% )
2,299,368 cache-references ( +- 0.13% )
535,940,231 instructions # 1.17 insn per cycle ( +- 0.00% )
457,889,685 cycles ( +- 0.15% )
0.159220105 seconds time elapsed ( +- 0.23% )
Performance counter stats for './test_ref --bench s Tai' (100 runs):
1,227,952 cache-misses # 43.083 % of all cache refs ( +- 0.42% )
2,850,183 cache-references ( +- 0.23% )
596,890,922 instructions # 1.07 insn per cycle ( +- 0.00% )
557,316,632 cycles ( +- 0.16% )
0.194107229 seconds time elapsed ( +- 0.25% )
```
仔細觀察程式碼就會發現,`test_ref.c`有使用 bloom filter,而`test_cpy.c`則無,減少了 cache miss 的次數,bloom filter 果然有奇效!
在此成功產生了`ref.txt`以及`cpy.txt`兩個檔案。
而`calculate.c`在`Makefile`中沒有進行編譯,看來得自己加了:
```makefile
cal: calculate.c
gcc -o calculate calculate.c
./calculate
```
真是太讚了,成功產生`output.txt`檔。
至於`bench_cpy.txt`以及`bench_ref.txt`也是由`test_cpy.c`以及`test_ref.c`的這段程式碼產生:
```c=
if (argc == 2 && strcmp(argv[1], "--bench") == 0) {
int stat = bench_test(root, BENCH_TEST_FILE, LMAX);
tst_free_all(root);
return stat;
}
```
因此在`Makefile`定義兩個參數的執行:
```makefile
one_test: test_cpy test_ref
./test_cpy --bench
./test_ref --bench
```
接著再加入繪圖功能:
```makefile
plot: one_test bench_cpy.txt bench_ref.txt output.txt
$(Q)gnuplot scripts/runtime.gp
$(Q)gnuplot scripts/runtime3.gp
$(Q)gnuplot scripts/runtimept.gp
$(Q)gnuplot scripts/runtimebox.gp
```
輸入指令`$ make plot`,感動的一刻終於到了,成功產生出三張圖片!
在`.gp`檔中稍微修改了一下輸出的檔名,不然我真的會搞不清楚到底每張圖的用處是什麼:
- `runtime.png`
![](https://i.imgur.com/GUKgk90.png)
- `cpy.png`
![](https://i.imgur.com/hFt6JWw.png)
- `compare.png`
![](https://i.imgur.com/8RXpe1C.png)