Perl で「ある値が、いくつかの値のどれかと同じか判定」するには、あらかじめ判定用のハッシュを作っておくのが定石だし、実際に速い。けど実際にどれぐらい速いのかな。
試してみる。手元の環境は Perl 5.14.2。どれかにマッチするのは 0.1% というケースでベンチマーク。
#!/usr/bin/perl use warnings; use strict; use Benchmark qw(cmpthese); use List::MoreUtils qw(any); foreach my $size (3, 10, 100) { my @a = (1 .. $size); my %h; $h{$_}++ foreach @a; cmpthese( -30, { "grep($size)" => sub { foreach my $i (1 .. $size * 1000) { my $exists = grep { $_ == $i } @a; } }, "any($size)" => sub { foreach my $i (1 .. $size * 1000) { my $exists = any { $_ == $i } @a; } }, "exists($size)" => sub { foreach my $i (1 .. $size * 1000) { my $exists = exists $h{$i}; } }, "make & exists($size)" => sub { foreach my $i (1 .. $size * 1000) { my %my_h; $my_h{$_}++ foreach @a; my $exists = exists $my_h{$i}; } }, } ); print "\n"; }
Rate any(3) make & exists(3) grep(3) exists(3) any(3) 107/s -- -33% -77% -87% make & exists(3) 160/s 49% -- -66% -80% grep(3) 471/s 339% 194% -- -43% exists(3) 820/s 665% 412% 74% -- Rate any(10) make & exists(10) grep(10) exists(10) any(10) 21.1/s -- -8% -67% -91% make & exists(10) 23.0/s 9% -- -65% -90% grep(10) 64.9/s 208% 182% -- -73% exists(10) 240/s 1036% 941% 269% -- s/iter make & exists(100) any(100) grep(100) exists(100) make & exists(100) 3.48 -- -50% -65% -99% any(100) 1.75 99% -- -30% -97% grep(100) 1.23 182% 42% -- -96% exists(100) 4.49e-02 7643% 3797% 2641% --
やはりハッシュを作っておいた方が速いね。ただし毎回その場で配列に入っているものからハッシュを作って判定処理するぐらいなら100個程度なら grep した方が速い。
配列の全件をほぼ毎回舐めることになる今回のケースでは any よりも grep の方が速い。
Happy Benchmarking!
Emacs の howm 上で書いたノートなどをさくっと共有したい時に、わざわざ Wiki 上や IRC 上や Google ドライブ上に転記したり更新したりするのが面倒なので、そのまま見られるようにしたいなと。
この間 howm で書く時のフォーマットを Markdown にしたので、howm-directory をそのまま Plack::App::Directory::Markdown で見られるように設定してみた。
完全じゃないけれど今のところこんな感じ。
(setq howm-file-name-format "%Y/%m/%Y-%m-%d-%H%M%S.md") (setq howm-view-title-header "#") (setq howm-view-title-regexp (format "^\\(%s|=\\)\\( +\\(.*\\)\\|\\)$" (regexp-quote howm-view-title-header))) (setq howm-view-title-regexp-pos 3) (setq howm-view-title-regexp-grep (format "^(%s|=) +" (regexp-quote howm-view-title-header)))
非公開用 howm-directory と公開用 howm-directory は
の通り下記のように設定。
(defun my-howm-set-directory (dir &optional keyfile) `(lambda () (interactive) ;; kill current keyword buffer first to avoid the error ;; "howm-get-buffer-for-file: Buffer name ` *howm-keys:*' is in use" (kill-buffer (howm-keyword-buffer)) (setq howm-directory ,dir) (when ,keyfile (setq howm-keyword-file ,keyfile)) (setq howm-menu-next-expiry-time (current-time)) (message "%s" ,dir))) (defun my-howm-switch-directory (dir &optional keyfile) (funcall (my-howm-set-directory dir keyfile)) (howm-menu)) (global-set-key "\C-c,1" (my-howm-set-directory "~/var/howm/" "~/.howm1-keys")) (global-set-key "\C-c,2" (my-howm-set-directory "~/srv/howm/" "~/.howm2-keys"))
cpanm でインストール。簡単に起動するなら付属の pad-markdown.pl で。
#!/bin/sh PAD_MARKDOWN=$HOME/local/perl5/perlbrew/perls/perl-5.18.2/bin/pad-markdown.pl ROOT=$HOME/srv/howm PORT=9119 $PAD_MARKDOWN --root=$ROOT --encoding=utf8 --title='howm' --port=$PORT &
これで後は C-c,2 C-c,c で howm ノートを作って保存すれば http://HOST_NAME:9119/2014/03/2014-03-17-231015.md ですぐ見られるようになる。あるいは ~/srv/howm/ 以下に適当に .md ファイルを作ってもよい。適当に楽ちん。
欲を言うと検索できるようにしたりページ間リンクを簡単に張れるようにしたりとかしたいなあと思うのだけれど、そのまま進むと(フォーマットこそ違えど)この nDiki の DiKicker と同じ機能になってくるので、今はそこまでしなくてもいいかな。その時に他人にシェアしたいのはピンポイントで1ページだけがほとんどだし、自分自身は howm 上で検索できるし。
こう考えてみると「Emacs でプレーンテキスト」で「書いて保存すれば(あるいはそしてリモートに同期すれば) 明示的な変換作業しないで勝手に公開」されて、書く場所は「年月別ディレクトリ」とか「デイリーなノートとは別のページが作れる」とか「検索も grep レベルできる」とか、まあ結局自分が欲しいものは昔から変わらないなあ。
ここ最近プライベート日記はスマートフォンアプリを使っていて、今は Day One を使っている。一方公開日記は Web 日記としてこの nDiki をつけている。前者は完全非公開、後者は全体公開。
たまに特定グループ向けに公開したいなと思ったりするのだけれど、身近に使えるのはやはり自分の場合mixi日記かな。ただ日記メディアとして便利なんだけれど、自分はローカルホスト上で grep できるように手元にも記事ファイルを置いておきたい(Emacs + howm で検索したい)。
ということでグループ公開したい日記は Day One で書いて、mixi日記に上げるようにしてみようかなと。これならスマートフォンでも草稿かけるしアプリ上でプライベート日記と同じタイムラインに並べて見られるし、 Dropbox に XML エントリファイルが作られるので Linux 上で grep がかけられるし。
で一度手順を流してみた。iOS デバイス上で完結させるとどれぐらいの手順になるかどうか、 Publish 公開も含めてやったのが以下。
日時を統一したり permalink を取得して書き込み直したりしているので手順がちょっと多いけれど、実際にはグループ公開の場合は Publish しないのでもっと少ない手順になる(写真を載せると逆にもうちょっと手間がかかる)。あと PC 使っている普段の状況なら Emacs + Google Chrome でさっとやってしまうのでもっと楽。やれば自動化もできるとは思うけれどもそこまではいっかな。
あとで整理してまとめたりできるように、ふと思ったことを非公開で1人 Twitter タイムライン的にログっておくのに PC 上でなかなかいいのないんだよねとずっと思っていたんだけれど Emacs の Org mode にある Org Capture 試してみたらいい感じだった。
普段 Org mode 使っていないので Org Capture で必要なところだけ設定してみた。
(require 'org) (setq org-capture-templates '( ("t" "Timeline (local)" plain (file (concat "~/var/timeline/timeline-" (format-time-string "%Y-%m-%d") ".md")) "- [%(format-time-string \"%Y-%m-%d %H:%M:%S\")] %?\n") ("n" "Note (local)" plain (file (concat "~/var/note/" (format-time-string "%Y-%m-%d-%H%M%S") ".md")) "# %?\n[%(format-time-string \"%Y-%m-%d %H:%M:%S\")]\n") ("T" "Timeline" plain (file (concat "/naney@example.com:/home/naney/var/timeline/timeline-" (format-time-string "%Y-%m-%d") ".md")) "- [%(format-time-string \"%Y-%m-%d %H:%M:%S\")] %?\n") ("N" "Note" plain (file (concat "/naney@example.com:/home/naney/var/note/" (format-time-string "%Y-%m-%d-%H%M%S") ".md")) "# %?\n[%(format-time-string \"%Y-%m-%d %H:%M:%S\")]\n"))) (global-set-key (kbd "\C-cc") 'org-capture)
'C-c c t' すると
- [2014-03-25 23:24:25]
が書かれたバッファが開くので適当に何か書いて C-c C-c する。と、~/var/timeline-2014-03-25.md にその内容が追記される。
TRAMP でリモートホスト上のファイルを開く時のファイル名を指定してみたらうまくいったので、さくっとリモートファイルにも追記できてすごく嬉しい。ので 'C-c c T' で書き込めるように設定してみた。これで Dropbox や rsync / Unison などで同期する必要がなくていろいろ良い。
あとは追記型ではなくて都度新しくノートファイルを起こすタイプの設定も追加しておいた('C-c c n' と 'C-c c N' で呼び出し)。howm で 'C-c , c' するのと同じ感覚で作れる。こちらもリモートホスト上にファイル名で悩む必要なくさくっとノートを書いておくことができて良い(そのかわり howm みたいに grep できないけれど)。
リモートホスト上のファイルへの保存の方を良く使うので、'C-c c' の後のキーは小文字の方をリモートに、大文字の方をローカルに変更。
最近ノートやちょっとしたドキュメントは Markdown で書いて、Plack::App::Directory::Markdown (記事) (に手を入れて grep 検索や recent リストを表示できるようにした) Markdown ビューアで参照したり、関係者に見せたりしている。
重宝しているんだけれど、内部で使っている Text::Markdown Perl モジュールは、テーブルや GitHub Flavored Markdown にある fenced code blocks (``` で挟むやつ) が使えないのでちょっと不便になってきた。
Text::Markdown::Discount Perl モジュールはこの辺の拡張が使えるので、こちらに切り替えることにした。
このモジュールは discount というC言語書かれた Marrkdown 処理コードを使うもので、Text-Markdown-Discount 内に同梱されている。
そのままインストールすると fenced code blocks が有効になっていないので以下のようにしてインストールする。
$ tar zxvf Text-Markdown-Discount-0.11.tar.gz $ cd Text-Markdown-Discount-0.11 ここで Makefile.PL 中の qq{( cd $extdir; CC='cc -fPIC' sh configure.sh; make )\n} を qq{( cd $extdir; CC='cc -fPIC' sh configure.sh --with-fenced-code; make )\n} に変更する。 $ cpanm .
で Text::Markdown::markdown() のかわりに Text::Markdown::Discount::markdown() を使うようにすれば OK。
なお自動リンクをしたい時には
my $html = Text::Markdown::Discount::markdown($markdown_text, Text::Markdown::Discount::MKD_AUTOLINK);
のようにオプションを指定してあげる。
Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。