関数/メソッドのコード行数の累積グラフを表示する

Software Design 2013年08月号の第2特集にて、コード行数(LOC)の累積グラフがジニ係数のグラフに似ているとの記述があった。

id:eel3:20120116:1326675419 で書いたように、私の手元にはfunclenというC言語用の行数計測ツールがある。

$ funclen <cmd_parser.c
   26   eprintf
    1   cmd_parser_set_progname
   13   cmd_parser_init
    5   cmd_parser_reset
    8   iscmdsep
   11   skip_cmd_seps
   11   skip_comment
   16   iseol
  120   cmd_parser_read

$ _

この出力のような、空白区切りで先頭のフィールドに関数/メソッドの行数が書かれたテキストレコードを入力として、コード行数の累積グラフを表示するツールを作ってみた。

入力されるデータは個々の関数の行数になるので、awk(1)で累積の行数に変換して、gnuplot(1)でグラフ化すればよい。

#!/bin/sh
# funcgini - 各関数ごとの個別の値を元に、累積グラフを表示する
# (Cygwin + wgnuplot)

readonly progname=`basename "$0"`

trap 'rm -f "$tmpfile"; exit 1' 1 2 15

tmpfile=`mktemp "$progname.$$.XXXXXXXXXX"`
if [ $? -ne 0 ]; then
    echo "$progname: cannot create temporary file" 1>&2
    exit 1
fi

awk '
BEGIN {
    # plot start from {X: 0, Y: 0} (for gnuplot)
    print 0
}
{
    n += $1
    print n
}' ${@+"$@"} >"$tmpfile"

wgnuplot -e 'plot "'"$tmpfile"'" with linespoints; pause -1'

rm -f "$tmpfile"

実行環境が「Cygwin + gnuplotWindowsバイナリ」なので、wgnuplotを使用している。試してはいないが、wgnuplotの呼び出し部分を少し修正するだけでUnix環境でも使えると思う。

awkのBEGIN節で0を出力している。折れ線グラフをX == 0, Y == 0の座標から表示させるためのad hocな対応だ。

使い方はこんな感じ。

funclen <cmd_parser.c | funcgini

横軸(X軸)は関数の個数、縦軸(Y軸)は関数のコード行数の累積値となる。

ここでは関数の行数の累積グラフを表示しているが、それに限らず「個々の数値から累積グラフを表示する」という目的に使えるはず。

コード行数の累積グラフを実際に見てみて分かったこと:

  • 大きな関数(行数の多い関数)があると、折れ線の角度が急勾配になる。
  • ファイル先頭から関数が出現した順にコードの累積値を出力した場合:
    • 大きな関数がファイル末尾に偏っていると、ジニ係数ゼロのグラフよりも下の位置に折れ線がプロットされる。
    • 大きな関数がファイル先頭に偏っていると、ジニ係数ゼロのグラフよりも上の位置に折れ線がプロットされる。

ある人が新規に作成したソースファイルについてグラフ化したデータを集めてみたら、もしかしたら作成者の個性(何らかの傾向)が見られるかもしれない。