Hatena::ブログ(Diary)

Alone Like a Rhinoceros Horn

2011-12-28

Vim script のベンチマーク

数万回くらい実行されるループの中で文字列が空かどうかを調べなければならないとする。

  • empty(str)
  • str == ""

さて、どちらがいいだろう? empty() を使う方が、文字列が空かどうかを調べる、という意図が明確になっていいような気がするが、empty() の方は関数呼び出しなので、ひょっとすると ==演算子に比べて相当遅いかも知れないぞ……

この手の疑問/迷いを解消するために、同じことをする複数の Vim script コード片の速度性能を簡単に比較できるツールを作ってみました。

+reltime と +float が必要。7.2以降の Vim なら多分大丈夫(だと思うけど自信はないw)

使い方はこんな感じ。最初の疑問を解消すべく、ベンチマークスクリプトを作ってみる。

let s:bm = benchmark#new("String is empty?")

let s:N = 10000
let s:str = "hello"

function! s:bm.empty()
  let i = 0
  while i < s:N
    if empty(s:str)
    endif
    let i += 1
  endwhile
endfunction

function! s:bm.op_equal()
  let i = 0
  while i < s:N
    if s:str == ""
    endif
    let i += 1
  endwhile
endfunction

function! s:bm.op_match()
  let i = 0
  while i < s:N
    if s:str =~ '^\s*$'
    endif
    let i += 1
  endwhile
endfunction

call s:bm.run(3)

で、:source % または :QuickRun すると……

Benchmark: String is empty?

Trial #1
  op_equal : 0.078297
  empty    : 0.086356
  op_match : 0.114139

Trial #2
  op_equal : 0.080296
  empty    : 0.086518
  op_match : 0.109003
    
Trial #3
  op_equal : 0.080530
  empty    : 0.091485
  op_match : 0.118427

こういう結果が得られます。

所要時間にはループのコストも含まれていて、実はそれが所要時間の半分以上を占めていたりするので*1、これがそのまま ==演算子と empty() の速度差というわけではないものの、whileループの中に置いた場合の差は大体この程度、というのがわかります。(空の whileループの所要時間も同時に計測すれば、ループのコストを差し引いたおおよその速度差も検証できるはず)

Vim script を書いていて、ある処理を記述する複数の書き方のどれを選択するかで迷ったとき、これを使って速度比較を行ってみると、思わぬ発見があるやも。


もっと詳細に性能の評価を行いたい場合は……

このスクリプトのように、ループの中身が1行だけみたいな場合、ループ自体のコストが無視できないレベルになるので、このツールは対象コードの純粋な性能評価には向いていません。どちらかというと複数ある選択肢の中のどれが一番いいか、を比較するためのものです。

もっと詳細に行単位で性能を評価したいとか、全体のボトルネックを突き止めたいとかいった場合には、Vim のプロファイル機能を利用するべきでしょう。

*1Vim script の while は for に比べて相当遅いです。付属のサンプル参照。

2011-09-11

日本語プログラミング言語探訪 〜TTSneo〜

TTSneo

概要

TTSneo公式サイト


日本語プログラミング言語「TTSneo」は、日本語で気軽にプログラムを作ることができるスクリプト言語です。


* テキストエディタメーラー、イメージビューアなどソフト作りに最適

* プログラミング未経験の方でも分かりやすいマニュアルとサンプル

* ファイルの整理や圧縮、データ処理など操作を自動化

* マウスでウィンドウをデザインする機能など開発環境も充実

* プラグインを使って機能の拡張可能

サンプル

公式サイトより。

ウィンドウ1の作成
ウィンドウ1を表示する
待機する

手順は ウィンドウ1の作成
’<ウィンドウ1>
ウィンドウ1を使う
  その名前を「ウィンドウ1」へ変える
  その背景を&h8000000Fへ変える
’<メニュー>
  メニュー 「ウィンドウ(&W)」を作れ
  サブメニュー 「常に手前」を手前チェックとして作れ
’</メニュー>
  ウィンドウ1の中の大きさを(304,209)へ変える
’</ウィンドウ1>
終わり
手順は ウィンドウ1のウィンドウ(&W)の手前チェックをクリック
  状態は、メニューのウィンドウ(&W)の手前チェックのチェック
  状態は、1−状態
  メニューのウィンドウ(&W)の手前チェックのチェックは、状態
  ウィンドウ1の最前面を状態に変える
終わり
メモ
  • WindowsGUIアプリ作成が主な用途?
    • TTSneoデザイナという開発環境が付属
  • 個人が趣味で開発とのこと
    • しかし、公式サイトの充実度はすごい!

最後の資料より。

  • ウイルスの開発に使われたという実績(?)がある。
資料
  1. TTSneo - Wikipedia

2011-03-01

ctags を使った見出し抽出

C, C++, Java…… この辺の言語の見出し抽出を、正規表現を使ったパターンマッチングで行うのは限界にきていた(というか最初から無理な話であったw)ので、見出しの抽出ロジックを outline info が独自に定義できるようにした。

設定したパターンにマッチしたら create_heading() が呼ばれる、というこれまでの受け身な方法と違い、新しい方法ではバッファのパース自体を outline info側で行う。

これにより、outline info は外部の構文解析プログラムを呼び出すなどの方法が採れる*1ようになり、見出し抽出に ctags を使ったりできる。

で、その ctags を使用して見出しの抽出を行う outline info 第1号が完成した↓

f:id:h1mesuke:20110304022017p:image

C++用

C++用の outline info は「正規表現をこねくりまわして無理くり」な感じがありありと出ていて、見出しの一覧もかなり残念なものだったが、これでやっと本当に使えるレベルになったと思う。*2

outline info はひとつ作ると同じ要領で他のファイルタイプへと水平展開が容易なので、ctags が対応している他の言語用の outline info の改善/作成をこれからやっていこうと考えている。とりあえず最優先は C と Java。

ctags が対応しているものの、正規表現によるパターンマッチで実用的な見出し抽出ができている言語*3についてはどうしようか迷っている。大幅な速度向上などが見込めるならやるべきかも知れないが、そう安易に外部プログラムに依存するのもどうかと思うし悩ましいところ。*4

*1:unite-outline は outline info がどのようにして見出しを抽出するかには関知しない。

*2:というか、正規表現で無駄な努力をし過ぎたw 最初からそうしとけよと。

*3:見出しとなる行に必ず予約語があるタイプの言語。スクリプト言語の多くはこれに該当する。

*4:ctags がなければ既存の実装に fallback するという線もあるけど、保守がめんどくなりそう。

2011-01-11

ニコニコ動画の検索結果フィルタおよび USConfig 開発終了のお知らせ

最初のリリースからちょうど一年が経過した Nicovideo Results Filter ですが、誠に勝手ながら現在のバージョン(0.2.7_2010-11-21)をもって開発を終了させていただきます。今後、ニコニコ動画の方でページの仕様変更などがあり、スクリプトが動作しなくなっても対応できませんのでご了承ください。

また、これに関連して、Greasemonkeyスクリプトに設定画面を提供するライブラリとして開発を進めていた USConfig も開発を終了させていただきます。これは元々 GM_config の代替として Nicovideo Results Filter で使うために書いたものであり、自分としては今後これを使った Greasemonkeyスクリプトを書く予定もないので、NRF の開発終了を期に機に、こちらも開発終了とさせていただきます。

事情、あるいは理由
  • ある日突然ページの HTML が変わってスクリプトが動かなくなる → 更新しなければ! の流れが正直面倒くさい上にしんどい

    去年一年間でだいぶ懲りました。ある日突然ページの HTML が変わってスクリプトが動かなくなる、みたいなことがこちらの都合に関係なく起こるので、無理から時間を作って対応とか、正直しんどいです。かといって放置するのも精神衛生に悪いし。

    余暇を使ってやっているのに、自分のペースでやれないのはきついです。*1
  • 自分の時間リソースを他のものに割り当てたい

    やりたいことは他にもいろいろあるわけで……

まあそんな感じです。

ソースコード

NRF, USConfig ともにソースコードを MIT License にて公開していますので、自由に改変、再配布していただいて結構です。というか、むしろ歓迎。

USConfig の方は GitHub の方にリポジトリがあります。fork して更新を push したとしても pull request は不要です。

MIT License の日本語訳および原文はこちらです↓

以上です

ご愛顧ありがとうございました。

*1:その上面白くもないし。

2010-10-31

ニコニコ動画の検索結果フィルタをアップデート

をアップデートしました。

原宿へのリニューアルによって「タイトル」フィルタと、キャッシュを利用するフィルタ全般が正常に動作しなくなっていたのを修正しました。機能の追加などはありません。

2010-10-21

USConfig - 旧バージョンのタグを削除しました

でお知らせしている通り、初回のロード(ブラウザに設定がまた保存されていない状態でのロード)に不具合のあった v1.10未満のバージョンについて、GitHub のレポジトリからタグを削除しました。

GitHub のページの「Downloads」から、これらの不具合のあるバージョンが、(あたかも stable であるかのごとく)ダウンロード可能な状態にあることを問題と考えたためです。

直に @require されている可能性を考慮すると、タグの削除は暴挙である可能性大なのですが、以下の理由から削除に踏み切りました。

  • そもそも使われていないだろう
    あれだけの不具合、自分で見つけるまで誰からも報告がなかったことを考えると、まだまだ知名度も低く、使っている人も少ないに違いない(もしかすると皆無かも)
  • 使い続けられても困る
    仮に削除したタグを直に指定して @require しているスクリプトがあったとしても、上記の不具合を抱えているわけなので、そのまま使い続けられても困る。むしろ使えなくすべき。

stable でないものにタグを付けてしまうとこういった問題になるということで、今後は慎重にやりたいと思います。

2010-10-13

USConfig v1.11 をリリース

の v1.11 をリリースしました。

改善点

v1.0x では Config.load() まわりで大ポカをやらかしており、

  • スクリプトの初回インストール後(まだブラウザに設定が保存されていない状態の時)、設定画面から最初に「保存」するまで Config.load() が空オブジェクト({})を返す。(その結果、defaults が返ることを期待しているスクリプトは落ちる)
  • 新しく追加した設定項目も、設定画面を通して「保存」されるまでは Config.load() が返すオブジェクトでは undefined

といった問題がありました。設定画面ライブラリとしては重大な問題で、該当バージョンの USConfig を使われている方は、大変申し訳ありませんが最新バージョン(v1.11)へのアップデートをお願いいたします。

元々 GM_config が保存した設定を継承し、GM_config を置き換えるために書いたという経緯のため、ブラウザに設定が保存されていない状態でのテストが抜けていたのが問題の発見が遅れた原因です。

テスト態勢の不備が露見する形となり、非常に恥ずかしい限りです。今後はテスト態勢の充実に努め、より堅実なリリースを心がけます。

告知

USConfig に関しては、cross-browser対応をはじめ、まだまだ改善の余地があります。今後も継続的に機能の追加、改善を行っていく予定で、大きな変更があればこのブログで告知しようと思います。

2010-08-04

ニコニコ動画の検索結果フィルタをアップデート

をアップデートしました。

ニコニコ動画の検索結果HTML の変更の影響で、

  • ○列表示の認識失敗
  • 検索結果中の動画件数カウント失敗
  • テーブルを詰め直す際に削除されるべきでない動画まで削除
  • 表示動画と削除動画の件数の辻褄が合わない

といった諸々の問題が発生していたので、これらをすべて修復しました。