/proc/meminfoのviewerをつくった

# やりたいこと
`/proc/meminfo`の内容を理解するために、色々実験しながら各要素の変遷が見たい。
ただ、メモリ使用状況を可視化するツールはたくさんあるがどれも抽象度が高く、
/proc/meminfoの粒度での変遷を表示するツールを見つけられなかった。

# やったこと
`/proc/meminfo`をできるだけそのまま表示する[miviewer](https://github.com/takeoverjp/miviewer)をつくった。
といっても`/proc/meminfo`を取得して積み上げグラフにしただけ。


![active.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37714/e0543e64-7b67-c9f8-6549-9b9daf811679.png)

# [miviewer](https://github.com/takeoverjp/miviewer)

```shell-session
$ ./miviewer.py -h
usage: miviewer.py [-h] [-a] [-i INTERVAL] [-c COUNT] [--check] [-w WINDOW]
                   [-t {active,buff-cache,available,user-kernel}]

optional arguments:
  -h, --help            show this help message and exit
  -a, --adb             Get meminfo via adb.
  -i INTERVAL, --interval INTERVAL
                        The delay between updates in milli-seconds. Default is 200.
  -c COUNT, --count COUNT
                        Number of updates. Default is infinite.
  --check               Check some formulas.
  -w WINDOW, --window WINDOW
                        Shown period time in seconds. Default is 60.
  -t {active,buff-cache,available,user-kernel}, --type {active,buff-cache,available,user-kernel}
                        Graph type. Default is active.
```

デフォルトでは、スクリプトを実行したPCの`/proc/meminfo`を、200ms間隔で取得し、グラフにプロットする。
`--adb`オプションを指定することで、`adb`経由でAndroid端末の`/proc/meminfo`を取得することも可能。
また、`/proc/meminfo`の要素はそれぞれ重なりがあり、一つの積み上げグラフですべての要素を表示することはできないので、
４つの選択肢からグラフタイプを選択できるようにしている。


## グラフタイプ`active`

デフォルト。
Activeかどうか、つまり、LRUリストに乗ってるかどうかで分類された要素を積み上げている。
冒頭のグラフはこのタイプ。
なお、凡例の要素名が@で始まるものは、それそのものが`/proc/meminfo`にあるわけではなく、何らかの方法で算出した値であることを示す。

![active.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37714/9f615068-b3af-47da-e965-154bff7df85a.png)

## グラフタイプ`buff-cache`

`Buffers`と`Cached`、つまりバッファキャッシュ(メタデータやraw I/O用のキャッシュ)とページキャッシュ(ファイル自体のページのキャッシュ)の変遷を見るとき用。

![buff-cache.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37714/aa47c48f-192c-4162-33a2-a0bf7b43e411.png)

## グラフタイプ`available`

シンプルに`MemAvailable`とそれ以外を表示する。
Linux観点でSwappingが始まるまでの余力をザクッと見るとき用。

![available.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37714/9d764566-016a-5f26-cf15-185d93a32faa.png)

## グラフタイプ`user-kernel`

ユーザ空間とカーネル空間のどちらで使っているかで分類してプロットする。
なんか使うことがあるかなとおもって用意したものの、デフォルトの`active`があれば必要ない気がしないでもない。

![user-kernel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37714/d2e9d1e6-17c6-ae4c-e2fe-7092b08899bc.png)


# 環境
動作確認環境は、以下のとおり。

- Ubuntu 18.04
- Linux 5.0.0-29-generic
- Python 3.6.8
- matplotlib 2.1.1

とはいえあまり環境に依存する実装ではないので、
`MemAvailable`がある(3.14以降)Linux環境なら動くんじゃないかと。
もしかしたら`adb`モードならMac/Windowsでも動くかもしれない(未確認)。


# おわりに
なにかお気づきの点やご要望などありましたらぜひご指摘ください。

# 参考
- `/proc/meminfo`
  - [proc.txt - kernel.org](https://www.kernel.org/doc/Documentation/filesystems/proc.txt)
  - [/proc/meminfoを考える - めもめも](http://enakai00.hatenablog.com/entry/20110906/1315315488)
  - [【RHEL】linuxメモリのfreeとmeminfoの関係を図解し利用率の計算方法を説明してみる - のぴぴのメモ](http://nopipi.hatenablog.com/entry/2015/09/13/181026)

- `matplotlib.animation`
  - [matplotlib.animation — Matplotlib documentation](https://matplotlib.org/api/animation_api.html)
  - [Python: matplotlib で動的にグラフを生成する - CUBE SUGAR CONTAINER](https://blog.amedama.jp/entry/2018/07/13/001155)

- `matplotlib.stackplot`
  - [matplotlib.pyplot.stackplot - Matplotlib documentation](https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.pyplot.stackplot.html)
  - [matplotlib - stackplot で積み上げ折れ線グラフを作成する方法について- Pynote](http://pynote.hatenablog.com/entry/matplotlib-stackplot)