linuxBean14.04(40)pycallgraphでPythonのコールグラフ:その1

ラベル: ,

前の関連記事:linuxBean14.04(39)Pythonのパッケージ管理をPyCharmで行う


pycallgraphを使ってPythonのコールグラフを出します。最終的にはLibreOffice5のバンドルPythonからコールグラフをだせるようにします。まずはpycallgraphのインストールと出力されたコールグラフの色の意味について調べました。

pycallgraphとgraphvizのインストール


pycallgraphはPyCharmのsettings→Project:python→Project Interpreterで/usr/bin/python3.3を選択した状態でpycallgraphをインストールします。


linuxBean14.04(39)Pythonのパッケージ管理をPyCharmで行うのpthファイルを設定してあるとインタープリターを/opt/libreofficedev5.0/program/pythonにしたときもpycallgraphがパッケージにでてきます。

次にSynapticパッケージマネージャからgraphvizをインストールします。


これで準備完了です。

Terminalからgraphviz --helpとすると使い方が表示されるはずです。

pycallgraphでコールグラフを出力する


まず手始めにlinuxBean14.04(38)LibreOfficeバンドルPythonにパッケージを追加で使ったsite.pyのコールグラフを見てみます。

pycallgraph graphviz /usr/lib/python3.3/site.py
pq@pq-VirtualBox:~$ pycallgraph graphviz /usr/lib/python3.3/site.py
sys.path = [
    '/home/pq',
    '/usr/local/bin',
    '/usr/lib/python3.3',
    '/usr/lib/python3.3/plat-i386-linux-gnu',
    '/usr/lib/python3.3/lib-dynload',
    '/home/pq/.local/lib/python3.3/site-packages',
    '/usr/lib/python3/dist-packages',
    '/usr/local/lib/python3.3/dist-packages',
]
USER_BASE: '/home/pq/.local' (exists)
USER_SITE: '/home/pq/.local/lib/python3.3/site-packages' (exists)
ENABLE_USER_SITE: True
出力結果は/usr/bin/python3.3  /usr/lib/python3.3/site.pyを実行したときと全く同じです。

pycallgraphの結果はpycallgraphを実行したフォルダにpycallgraph.pngというファイル名で出力されています。

3521x2040ピクセルもある巨大pngファイルです。

ダウンロードして拡大して見ないとよくわからないと思います。



同じファイルをWindowsフォトビューアーで見るとlinuxBeansのイメージビューワより文字が見にくいのはなぜだろうか、、、Windows7ではChromeで開いたほうが綺麗に見えました。

ちなみにlinuxBean14.04のデフォルトイメージビューワGPicViewでは、左のCtrlボタンを押しながらマウスホイールを回すと画像の拡大/縮小ができます。

彩度が高いノードが改善効果がでやすい部分


Customisable colors. You can programatically set the colors based on number of calls, time taken, memory usage, etc.
Python Call Graph — Python Call Graph 1.0.1 documentation
呼び出し回数や占有時間、メモリー消費量を元に色のカスタマイズができると書いてあるのですが、カスタマイズのやり方を書いてある資料を見つけられませんでした。


先ほどのコールグラフをよく見てみると、timeの数値が大きい頂点(vertex,node)(以下ノードと呼称)ほど灰色から紫色に近くなっているようです。

ノードを結ぶ矢印(枝、branch,edge)(以下エッジと呼称)は行き先の色と同じになるようです。

(グラフの用語はPython(7)二分木(Binary Tree)の勉強資料を求めて本屋へで購入した教養のコンピュータアルゴリズムのP65によりました。)

エッジに付随する数値はその先のノードを呼び出した回数になっています。

/usr/local/lib/python3.3/dist-packages/pycallgraph/color.pyを読むとr,g,bを何か計算しているようです。
class Stat(object):
    '''Stores a "statistic" value, e.g. "time taken" along with the maximum
    possible value of the value, which is used to calculate the fraction of 1.
    The fraction is used for choosing colors.
    '''

    def __init__(self, value, total):
        self.value = value
        self.total = total
        try:
            self.fraction = value / total
        except ZeroDivisionError:
            self.fraction = 0
「color」でpyファイルを検索してみると同じフォルダにあるtracer.pyにあるStatクラスのところにこんな記述を見つけました。

例えば、占有時間の全体に対する割合を算出してその数値(fraction)を色の設定に使っているようです。
    def node_color(self, node):
        value = float(node.time.fraction * 2 + node.calls.fraction) / 3
        return Color.hsv(value / 2 + .5, value, 0.9)

    def edge_color(self, edge):
        value = float(edge.time.fraction * 2 + edge.calls.fraction) / 3
        return Color.hsv(value / 2 + .5, value, 0.7) 
output.pyにfractionの値を使って色を計算している部分を見つけました。

結構複雑ですねえ。RGBではなくてHSVで計算していますし。

RGBとHSVも昔どこかで勉強した記憶がありますがこのブログを検索しても記事は出てきませんでした。

H:色相(Hue)、S:彩度(Saturation)、V:明度(Value) (HSV色空間 - Wikipedia

中学校の美術の時間で習ったやつです、、、教科書残しておけばよかった、、、

とりあえずノードの色についての計算式を展開してみます。

t:占有時間、c:呼び出し回数
$$v=\dfrac {1} {3}\left( \dfrac {2t} {\sum t}+\dfrac {c} {\sum c}\right)$$
ノードの色
$$\left( H,S,V\right) =\left( \dfrac {v+1} {2},v,0.9\right) $$
エッジの色
$$\left( H,S,V\right) =\left( \dfrac {v+1} {2},v,0.7\right) $$
占有時間割合に2倍の重みをつけて呼び出し回数割合との加重平均$$$v$$$($$$0\leq v\leq 1$$$)を得て、色相$$$H$$$を$$$\dfrac {v+1} {2}$$$、彩度$$$S$$$を$$$v$$$、明度$$$V$$$を$$$0.9$$$(エッジは$$$0.7$$$)にしています。

エッジの色はノードの色をちょっと暗くしたものとわかります。

色相で1を加えて2で割っているのは色相が一周すると元の色に戻ってしまうから、、、ではなさそうですね

$$$v$$$が1のときにHは1になってしまいますし、、、でも$$$v$$$が0のときにHは0.5になるのでやっぱりそうかも。(すぐあとでやる彩度を1にしたコールグラフの結果を見ると色相は180度の水色から始まって360度の赤になるようになっているとわかりました。)

Hの違いは色相 - Wikipediaのスケールでわかりますが、彩度の変化が加わるとどっちが数値が大きいのか私には直感的によくわかりません。

彩度 - Wikipediaの色空間の横断面の図に対応させるとまだわかるかも。


彩度を1に決めうちしてやってみました。

鮮やかになりましたが、ノードのラベルが読みにくくなってしまいました。

不思議なことにグラフの形も変わってしまいました。

彩度を戻してやり直してみると少しずつグラフの形が違いました。

やっぱり彩度に変化があったほうがよいですね。

彩度が高いものが着目すべきものということですね。

これらの彩度が低くなるように改善すると処理速度が速くなるので、自分でプログラミングしているときはそこを重点的に改善しないといけないとわかるわけですね。

参考にしたサイト


Python Call Graph — Python Call Graph 1.0.1 documentation
Pythonのコールグラフを出力してくれるpycallgraph。

HSV色空間 - Wikipedia
pycallgraphでは各ノードの占有時間と呼び出し回数を元にノードの色相と彩度を変化させて出力します。

色相 - Wikipedia
色相を変えると色の種類が変わります。

彩度 - Wikipedia
彩度を変えると色の鮮やかさが変わります。

次の関連記事:linuxBean14.04(41)pycallgraphでPythonのコールグラフ:その2

PR

0 件のコメント:

コメントを投稿