2013/04/12


vimに起動プロファイラが実装された。
Patch 7.2.269

Patch 7.2.269
Problem:    Many people struggle to find out why Vim startup is slow.
Solution:   Add the --startuptime command line flag.
Files:      runtime/doc/starting.txt, src/globals.h, src/feature.h,
            src/main.c, src/macros.h

http://groups.google.co.jp/group/vim_dev/browse_thread/thread/fcce6570fc7f025c/1ab37514f5656c7b
--startuptime={fname}                                   *--startuptime*
                During startup write timing messages to the file {fname}.
                This can be used to find out where time is spent while loading
                your .vimrc and plugins.
                When {fname} already exists new messages are appended.
                {only when compiled with this feature}
Vim 地味だけどこれは大きい修正だと思う。
これまで遅いvimscriptを見つけ出すには、時間を計測出来る様なスクリプト書いて内部で":source"させるとか、重そうなのを勘で選んでpluginから外してみるとかと言った人間臭いソリューションしかなかったんですが、これで楽に遅いvimscriptを見つけ出せる。
起動時に"--startuptime"オプションを付けるだけです。
# vim --startuptime=foo.log
こんな感じに出力するファイル名を指定すると、以下のファイル(foo.log)が生成される


times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.016  000.016: --- VIM STARTING ---
000.238  000.222: Allocated generic buffers
001.693  001.455: locale set
001.731  000.038: GUI prepared
001.742  000.011: clipboard setup
001.764  000.022: window checked
003.195  001.431: inits 1
003.214  000.019: parsing arguments
003.218  000.004: expanding arguments
003.263  000.045: shell init
010.436  007.173: xsmp init
011.004  000.568: Termcap init
011.102  000.098: inits 2
011.356  000.254: init highlight
012.165  000.537  000.537: sourcing /usr/share/vim/vim72/debian.vim
013.170  000.586  000.586: sourcing /usr/share/vim/vim72/syntax/syncolor.vim
013.469  001.031  000.445: sourcing /usr/share/vim/vim72/syntax/synload.vim
051.935  038.345  038.345: sourcing /usr/share/vim/vim72/filetype.vim
052.067  039.779  000.403: sourcing /usr/share/vim/vim72/syntax/syntax.vim
052.151  040.671  000.355: sourcing $VIM/vimrc
055.440  000.296  000.296: sourcing /usr/share/vim/vim72/syntax/nosyntax.vim
056.259  000.507  000.507: sourcing /usr/share/vim/vim72/syntax/syncolor.vim
056.522  000.920  000.413: sourcing /usr/share/vim/vim72/syntax/synload.vim
056.608  001.570  000.354: sourcing /usr/share/vim/vim72/syntax/syntax.vim
056.747  000.027  000.027: sourcing /usr/share/vim/vim72/filetype.vim
056.967  000.106  000.106: sourcing /usr/share/vim/vim72/ftplugin.vim
057.171  000.092  000.092: sourcing /usr/share/vim/vim72/indent.vim
058.050  005.805  004.010: sourcing $HOME/.vimrc
058.076  000.244: sourcing vimrc file(s)
059.677  001.041  001.041: sourcing /home/mattn/.vim/plugin/autodate.vim
062.523  002.768  002.768: sourcing /home/mattn/.vim/plugin/calendar.vim
086.597  024.004  024.004: sourcing /home/mattn/.vim/plugin/codepad.vim
087.964  001.247  001.247: sourcing /home/mattn/.vim/plugin/dicwin.vim
089.372  001.342  001.342: sourcing /home/mattn/.vim/plugin/fastladder.vim
090.757  001.281  001.281: sourcing /home/mattn/.vim/plugin/gist.vim
092.049  001.227  001.227: sourcing /home/mattn/.vim/plugin/googlereader.vim
094.195  002.080  002.080: sourcing /home/mattn/.vim/plugin/matchit.vim
094.577  000.309  000.309: sourcing /home/mattn/.vim/plugin/perldoc.vim
096.699  002.063  002.063: sourcing /home/mattn/.vim/plugin/quickrun.vim
097.149  000.366  000.366: sourcing /home/mattn/.vim/plugin/sudo.vim
099.234  002.013  002.013: sourcing /home/mattn/.vim/plugin/taglist.vim
100.264  000.964  000.964: sourcing /home/mattn/.vim/plugin/tetris.vim
100.895  000.568  000.568: sourcing /home/mattn/.vim/plugin/verifyenc.vim
101.915  000.275  000.275: sourcing /usr/share/vim/vim72/plugin/getscriptPlugin.vim
102.494  000.517  000.517: sourcing /usr/share/vim/vim72/plugin/gzip.vim
103.116  000.544  000.544: sourcing /usr/share/vim/vim72/plugin/matchparen.vim
104.978  001.798  001.798: sourcing /usr/share/vim/vim72/plugin/netrwPlugin.vim
105.210  000.157  000.157: sourcing /usr/share/vim/vim72/plugin/rrhelper.vim
105.340  000.077  000.077: sourcing /usr/share/vim/vim72/plugin/spellfile.vim
105.814  000.392  000.392: sourcing /usr/share/vim/vim72/plugin/tarPlugin.vim
106.039  000.152  000.152: sourcing /usr/share/vim/vim72/plugin/tohtml.vim
106.482  000.383  000.383: sourcing /usr/share/vim/vim72/plugin/vimballPlugin.vim
106.882  000.344  000.344: sourcing /usr/share/vim/vim72/plugin/zipPlugin.vim
109.159  001.825  001.825: sourcing /home/mattn/.vim/chalice/plugin/alice.vim
109.530  000.301  000.301: sourcing /home/mattn/.vim/chalice/plugin/cacheman.vim
110.813  000.897  000.897: sourcing /home/mattn/.vim/chalice/plugin/datutil.vim
111.379  000.392  000.392: sourcing /home/mattn/.vim/chalice/plugin/dolib.vim
126.889  017.296  016.007: sourcing /home/mattn/.vim/chalice/plugin/chalice.vim
128.028  000.909  000.909: sourcing /home/mattn/.vim/chalice/plugin/datutil.vim
128.470  000.374  000.374: sourcing /home/mattn/.vim/chalice/plugin/dolib.vim
128.487  003.794: loading plugins
130.381  001.894: inits 3
131.144  000.763: reading viminfo
137.261  006.117: setup clipboard
137.304  000.043: setting raw mode
137.336  000.032: start termcap
137.499  000.163: clearing screen
167.107  029.608: opening buffers
167.376  000.269: BufEnter autocommands
167.384  000.008: editing files in windows
167.438  000.054: VimEnter autocommands
167.443  000.005: before starting main loop
320.531  153.088: first screen update
320.544  000.013: --- VIM STARTED ---
これを見るとvimrcと、codepad.vimの読み込みが遅い事が一目瞭然である。

ちなみにcodepad.vimを外して起動すると

times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.016  000.016: --- VIM STARTING ---
000.251  000.235: Allocated generic buffers
001.749  001.498: locale set
001.786  000.037: GUI prepared
001.797  000.011: clipboard setup
001.819  000.022: window checked
003.267  001.448: inits 1
003.287  000.020: parsing arguments
003.291  000.004: expanding arguments
003.338  000.047: shell init
015.880  012.542: xsmp init
016.455  000.575: Termcap init
016.555  000.100: inits 2
016.807  000.252: init highlight
020.289  000.617  000.617: sourcing /usr/share/vim/vim72/debian.vim
021.349  000.627  000.627: sourcing /usr/share/vim/vim72/syntax/syncolor.vim
021.634  001.058  000.431: sourcing /usr/share/vim/vim72/syntax/synload.vim
059.675  037.918  037.918: sourcing /usr/share/vim/vim72/filetype.vim
059.815  039.391  000.415: sourcing /usr/share/vim/vim72/syntax/syntax.vim
059.898  042.967  002.959: sourcing $VIM/vimrc
063.216  000.304  000.304: sourcing /usr/share/vim/vim72/syntax/nosyntax.vim
064.068  000.536  000.536: sourcing /usr/share/vim/vim72/syntax/syncolor.vim
064.332  000.951  000.415: sourcing /usr/share/vim/vim72/syntax/synload.vim
064.418  001.613  000.358: sourcing /usr/share/vim/vim72/syntax/syntax.vim
064.557  000.028  000.028: sourcing /usr/share/vim/vim72/filetype.vim
064.775  000.107  000.107: sourcing /usr/share/vim/vim72/ftplugin.vim
065.189  000.301  000.301: sourcing /usr/share/vim/vim72/indent.vim
066.131  006.131  004.082: sourcing $HOME/.vimrc
066.161  000.256: sourcing vimrc file(s)
067.835  001.098  001.098: sourcing /home/mattn/.vim/plugin/autodate.vim
070.712  002.793  002.793: sourcing /home/mattn/.vim/plugin/calendar.vim
071.928  001.142  001.142: sourcing /home/mattn/.vim/plugin/dicwin.vim
073.385  001.389  001.389: sourcing /home/mattn/.vim/plugin/fastladder.vim
074.731  001.280  001.280: sourcing /home/mattn/.vim/plugin/gist.vim
076.102  001.298  001.298: sourcing /home/mattn/.vim/plugin/googlereader.vim
079.975  003.793  003.793: sourcing /home/mattn/.vim/plugin/matchit.vim
080.426  000.318  000.318: sourcing /home/mattn/.vim/plugin/perldoc.vim
082.556  002.071  002.071: sourcing /home/mattn/.vim/plugin/quickrun.vim
083.004  000.362  000.362: sourcing /home/mattn/.vim/plugin/sudo.vim
085.061  001.985  001.985: sourcing /home/mattn/.vim/plugin/taglist.vim
086.098  000.967  000.967: sourcing /home/mattn/.vim/plugin/tetris.vim
086.747  000.587  000.587: sourcing /home/mattn/.vim/plugin/verifyenc.vim
087.533  000.257  000.257: sourcing /usr/share/vim/vim72/plugin/getscriptPlugin.vim
088.056  000.467  000.467: sourcing /usr/share/vim/vim72/plugin/gzip.vim
088.678  000.543  000.543: sourcing /usr/share/vim/vim72/plugin/matchparen.vim
090.576  001.835  001.835: sourcing /usr/share/vim/vim72/plugin/netrwPlugin.vim
090.808  000.150  000.150: sourcing /usr/share/vim/vim72/plugin/rrhelper.vim
090.945  000.084  000.084: sourcing /usr/share/vim/vim72/plugin/spellfile.vim
091.401  000.402  000.402: sourcing /usr/share/vim/vim72/plugin/tarPlugin.vim
091.638  000.157  000.157: sourcing /usr/share/vim/vim72/plugin/tohtml.vim
092.072  000.376  000.376: sourcing /usr/share/vim/vim72/plugin/vimballPlugin.vim
092.498  000.365  000.365: sourcing /usr/share/vim/vim72/plugin/zipPlugin.vim
094.842  001.839  001.839: sourcing /home/mattn/.vim/chalice/plugin/alice.vim
095.189  000.272  000.272: sourcing /home/mattn/.vim/chalice/plugin/cacheman.vim
096.477  000.918  000.918: sourcing /home/mattn/.vim/chalice/plugin/datutil.vim
097.079  000.415  000.415: sourcing /home/mattn/.vim/chalice/plugin/dolib.vim
112.786  017.536  016.203: sourcing /home/mattn/.vim/chalice/plugin/chalice.vim
113.924  000.909  000.909: sourcing /home/mattn/.vim/chalice/plugin/datutil.vim
114.370  000.379  000.379: sourcing /home/mattn/.vim/chalice/plugin/dolib.vim
114.386  003.571: loading plugins
116.239  001.853: inits 3
117.053  000.814: reading viminfo
123.322  006.269: setup clipboard
123.367  000.045: setting raw mode
123.397  000.030: start termcap
123.437  000.040: clearing screen
124.526  001.089: opening buffers
124.899  000.373: BufEnter autocommands
124.907  000.008: editing files in windows
125.967  001.060: VimEnter autocommands
125.979  000.012: before starting main loop
287.072  161.093: first screen update
287.085  000.013: --- VIM STARTED ---
30msも減っている事が確認出来る。実はcodpad.vimは内部でpythonインタプリタを呼び出しており、これがvimの起動を遅くしている原因となっています。

vimrc内部でどの部分が遅いかについては、個々に見ていくしか無いのだけれど、ちょっと最近vimの起動が遅いのよねぇ...奥さん...って人には持って来いだと思う。

ちなみに入ったばかりなpatchなので、試すにはソースからビルドするしか方法はありませんが、プロファイル用にvimをビルドしてみる...ってのもありかもしれませんね。
Posted at by




DSAS開発者の部屋:gitでバイナリファイルを気軽に扱えるフィルターを作りました

gits3 は Python でプロトタイプを作った後、 go で作りなおしました。

http://dsas.blog.klab.org/archives/52105107.html
S3、1年たったらタダちゃうし、Dropbox 使いたいよ... ってことで作ってみました。
mattn/git-dropbox - GitHub

Simulate hg largefile on git with dropbox Introduction When we want to add lar...

https://github.com/mattn/git-dropbox
使い方は DSAS さんのブログと同じです。まずインストール。 $ go get github.com/mattn/git-dropbox ~/.gitconfig.git/config にフィルタを登録します。 [filter "dropbox"]
    clean = git-dropbox store
    smudge = git-dropbox load
そしてリポジトリに .gitattributes というファイルを作り、以下の様にフィルタを割り当てます。 *.png  filter=dropbox
*.jpeg filter=dropbox
*.jpg  filter=dropbox
*.gif  filter=dropbox
あとは普通に git add するだけで、dropbox の Apps/git-store というフォルダに格納されていきます。
初回だけ、ブラウザが自動で起動しますのでそこで許可ボタンを押して頂く必要があります。
ローカルにもキャッシュを持っているので、他のユーザと共有する場合は、~/.gitasset/data というフォルダを rsync しておけばOKです。
もしくは dropbox 側で共有するというのもアリかもしれません。
なお、git-dropbox には -nocache というオプションもあるので、上記フィルタの登録時に [filter "dropbox"]
    clean = git-dropbox -nocache store
    smudge = git-dropbox -nocache load
-nocache を指定しておけばディスク容量が気になる方には良いかもしれません。

ちなみにコマンドラインから
$ git dropbox store fugafuga.txt < fugafuga.txt
$ git dropbox load fugafuga.txt
$ git dropbox drop fugafuga.txt
$ git dropbox list
という使い方も出来ます。
どうぞお役立て下さい。
Posted at by



2013/04/11


golang_bot 先日、Lingr がとてもホットなので「Go言語」部屋を作ったのですが、Lingr のしきたりとして、その開発言語でbotを書くというのがあったので(要出典)、go言語でbotを書いた。
mattn/go-lingrbot - GitHub
https://github.com/mattn/go-lingrbot
機能としては3つ。
  • URL が貼り付けられたらそのページのタイトルをお知らせする
  • !godoc math という発言があれば、math パッケージの説明とドキュメントの URL をお知らせする
  • mattn++ などという発言があれば、カウントアップして通算++数をお知らせする
Google AppEngine で動いてます。

URLボット

まず URL のタイトルをお知らせする部分、Go言語は内部エンコーディングが utf-8 であり、オフィシャルからはキャラクタセットを扱えるライブラリが提供されていません。かつ、Google AppEngine 上で動かすので CGO を使った物も動かせません。しかし mahonia というパッケージが CGO 無しでキャラクタセットを扱えるのでそれを使う事にしました。
mahonia - Mahonia - a character-set conversion library for Go - Google Project Hosting

Mahonia is a character-set conversion library implemented in Go. All data is compiled into the execu...

https://code.google.com/p/mahonia/
得られた HTML をパースして meta タグを調べ、キャラクタセットを得た後に、title タグの内容を utf-8 に変換しています。 if charset == "" && n.Type == html.ElementNode && n.Data == "meta" {
    kv := make(map[string]string)
    for _, a := range n.Attr {
        kv[strings.ToLower(a.Key)] = strings.ToLower(a.Val)
    }
    if v, ok := kv["http-equiv"]; ok && v == "content-type" {
        if v, ok = kv["content"]; ok {
            for _, t := range strings.Split(v, ";") {
                tt := strings.Split(strings.TrimSpace(t), "=")
                if len(tt) == 2 && strings.ToLower(tt[0]) == "charset" {
                    charset = tt[1]
                    break
                }
            }
        }
    }
    if v, ok := kv["charset"]; ok {
        charset = v
    }
}
if n.Type == html.ElementNode && n.Data == "title" {
    if charset == "" {
        charset = "utf-8"
    }
    title = mahonia.NewDecoder(charset).ConvertString(n.FirstChild.Data)
}

Godocボット

GoDoc

Popular Packages bitbucket.org/jaybill/sawsij/framework code.google.com/p/biogo code.google.com/p/go...

http://godoc.org/
github からGo言語のパッケージだけを集めてドキュメントを表示してくれるサイトを利用しました。
このサイトは Accept: text/plain ヘッダを付けて要求すると、テキスト形式で応答してくれる機能があったので、その結果からパッケージの説明を抽出しています。

プラスプラスボット

まず発言から mattn++
mattn--
mattn+=3
mattn-=5
などという発言を抽出します。 var rePlus = regexp.MustCompile(`^\s*([a-zA-Z0-9_{^}]+)\+\+\s*$`)
var reMinus = regexp.MustCompile(`^\s*([a-zA-Z0-9_{^}]+)--\s*$`)
var rePlusEq = regexp.MustCompile(`^\s*([a-zA-Z0-9_{^}]+)\+=([0-9])\s*$`)
var reMinusEq = regexp.MustCompile(`^\s*([a-zA-Z0-9_{^}]+)\-=([0-9])\s*$`)
func parsePlusPlus(message string, callback func(nick string, plus int)) bool {
    if rePlus.MatchString(message) {
        m := rePlus.FindStringSubmatch(message)
        callback(m[1], 1)
        return true
    } else if reMinus.MatchString(message) {
        m := reMinus.FindStringSubmatch(message)
        callback(m[1], -1)
        return true
    } else if rePlusEq.MatchString(message) {
        m := rePlusEq.FindStringSubmatch(message)
        callback(m[1], atoi(m[2]))
        return true
    } else if reMinusEq.MatchString(message) {
        m := reMinusEq.FindStringSubmatch(message)
        callback(m[1], -atoi(m[2]))
        return true
    }
    return false
}
そしてそこから呼ばれるコールバックで、GAE のデータストアに格納します。 parsePlusPlus(event.Message.Text, func(nick string, plus int) {
    plusplus := &PlusPlus{nick, 0}
    key := datastore.NewKey(c, "PlusPlus", nick, 0nil)
    err := datastore.Get(c, key, plusplus)
    if err == nil || err == datastore.ErrNoSuchEntity {
        plusplus.Count += plus
        _, err = datastore.Put(c, key, plusplus)
        results += fmt.Sprintf("%s (%d)\n", plusplus.Nickname, plusplus.Count)
    }
})
最後に通算++数を応答します。


これでだいたい、一般的な bot としての機能は満たせました。Lingr のGo言語部屋に24時間常駐しています。
お好きな様にお使い下さい。
Posted at by