Go版retriable作った
使い方
一番シンプルな使い方。引数として渡されたクロージャが成功するまでリトライし続ける。 リトライ回数のデフォルトは3で、リトライ間隔は randomized exponential backoff アルゴリズムを使っている。簡単に言うと、CSMA/CD みたいにコリジョン(失敗)すると次に実行するまでの時間が徐々に長くなっていくアルゴリズム(をちょっと変形させたやつで、元ネタはここらしい google-http-java-client )。
retriable.Retry(func() error { // your code return nil })
リトライ回数を変更したい場合は Options を使う。 リトライ回数を5、最初のリトライ間隔を1秒に設定した例。
opt := retriable.Options{ retries: 5, interval: 1 * time.Second, } retriable.RetryWithOptions(func() error { // your code return nil }, opt)
処理全体にタイムアウトを設定することも出来る。 RetryWithOptionsに渡されたクロージャが5秒以上かかった場合にリトライするのをやめて、処理を返えす。
opt := retriable.Options{ timeout: 5 * time.Second, } retriable.RetryWithOptions(func() error { // your code return nil }, opt)
リトライ間隔がexponentialに増加するのではなく、一定にしたい場合はbackoffをConstantBackoffに変更する。
opt := retriable.Options{ backoff: backoff.NewConstantBackOff(1 * time.Second), } retriable.RetryWithOptions(func() error { // your code return nil }, opt)
まとめ
ご意見があればぜひ
Rust で LLVM やってみる
Rust と LLVM やってみたくなってやってる. llvm-sys という LLVM の Rust バインディングのライブラリを使って LLVM 動かしてみた話と自分用メモ.
きつねさんでもわかるLLVMを読んでからやるかと思ったが,5章以降はちょっと自分には合わなかったのでブログ探して、それをやりながら参照程度に狐さんを見るという作戦でいった.
環境設定
何とかして Rust を入れる. これを真似すればだいたい行ける.
気付いたらRustの環境構築がかなり楽になってた | κeenのHappy Hacκing Blog
後は LLVM を入れてpathを通す.
brew install llvm export PATH="`brew --prefix llvm`/bin:$PATH"
やったこと
- LLVM IR の雰囲気を知りたかったので幾つかサンプル書いてみた.
playground/rust/llvm-example at master · ganmacs/playground · GitHub
llvm*.rsは上の方に動かしたい擬似コードを書いてある. codegen*.rs は AST ができてる体でそれを LLVM IR に変換するコードをかいた.
ほとんど Rust かいた経験がないため,色々おかしいところがありそう. マクロかけるようにするかってところで気持ちが終わり,LLVMバックエンドにリプレイスとかやってる.
参考になったブログとコード
llvm の公式のサイト.実際 LLVM IR 書いてる(実際に書いてるのはRustのラッパーだけど)と使い方がわからず,ググると大抵これしかヒットしないので一生懸命これを読む.
Rust で llvm-sys.rs を使って 数字を出すところから phi 関数(というのがある) を使って if 式を作ることまでやってる.
Go 言語用のバインディングもあるようでそれを使って,加算するところまでやってる.序盤の説明が分かりやすかった.
LLVM の外観をつかむのには良かった. ただ,読み進めてるといきなり Pass の話をしだすので,LLVM IR について知りたい場合は序盤だけ読んで,後半は後で読むと良さそう.
LLVM のチュートリアルを Rust でやってる. この作者が作った iron-llvm という llvm-sys.rs をラップしたライブラリを使って LLVM を触っているのでいきなりこれを見ること混乱するかもしれない. 最初はむしろ iron-llvm のコードを読んで llvm-sys.rs の使い方の雰囲気をつかむのが良い.
きつねさんでもわかる LLVM のサンプルコードのリポジトリ.割りと大きめのコードなので実際に真似しやすい. 構文の定義( https://github.com/Kmotiko/DummyCCompiler/blob/master/dummyC_ebnf.txt )を読めばどんな言語かわかるので本の方は読まなくてもだいたい分かると思う.
emacsでコード読んでるときに「現在いる行が含まれたプルリク」に飛びたいを見れるようにした
これ見て hub browse -- commit/<commit-id>
でcommitに飛べることを知ったので、それを使って emacsでコード読んでるときに「現在いる行が含まれたプルリク」に飛びたいを見れるようにした。
このスクリプトも元ブログと一緒でプルリクのページではなくコミットページを開くところで終わってますが。
(defun open-github-commit () (interactive) (let* ((cmd1 "git blame -l -L %s,+1 %s | cut -d ' ' -f 1") (cmd2 "hub browse -- commit/%s") (zero "0000000000000000000000000000000000000000") (commit-id (shell-command-to-string (format cmd1 (line-number-at-pos) buffer-file-name)))) (if (string= zero commit-id) (message "This line is not commited") (shell-command (format cmd2 commit-id))))) (global-set-key (kbd "M-g o") 'open-github-commit)
hub browse -- commit/<commit-id> でいけるのか昔自分の書いた軟弱な正規表現を修正しなくて済みそう最高
— がんま (@ganmacs) 2017年2月9日
さよならgheに対応してないelisp君 GitHub - ganmacs/emacs-github-open: Open a commit url in github.com
Treasure Data インターンで最高の夏過ごしてきた #td_intern
8月1日から9月30日の間,Treasure Data Summer Intern 2016に参加していました. 他のインターン生2人からの強烈なプレッシャー (強烈なプレッシャー1,強烈なプレッシャー2)に負けたので僕もインターンブログを書きます.
tl;dr
すごいメンターの元 Fluentd の開発してると何故かめっちゃお金がもらえるインターンでとにかく最高
なにやってたの?
キュートなロゴ
Fluentd というソフトウェアの v0.14 向けの機能を,メンターの @tagomoris さんの元,開発しました.具体的に行ったことは以下のようになります(スライドからそのまま持ってきただけですが).
- 6 features
- 2 enhancements
- Optimizing multiple filter calls
- Add event size to options in a forward protocol
- Some small tasks
インターン期間は2ヶ月あったので,最初の1ヶ月は Fluentd の開発スタイルに慣れようということで小さめの機能(Counter API以外のタスク)をいくつかをやって,最後の1ヶ月で大きい機能(Counter API)を1つ をやりました.
一応雑に機能を紹介すると,
Counter API
マルチプロセスでfluentd動かしたとき,メトリクスとるのに使えるやつ
Data compression in buffer plugins and forward plugins
データを圧縮して操作できるようになり何かとリソースを節約できるやつ
New out_file plugin only for
secondary セクションのみで使えるシンプルな out_file
プラグイン
A CLI tool to read dumped event data
送信に失敗してダンプされた MessagePack形式のデータを読めるようなるやつ
Log rotation
Fluentd で log rotation できるようになるやつ
filter_with_time method in filter plugins
filter pluginで time をいじれるようにするやつ
Optimizing multiple filter calls
複数filter使用したときに高速化するやつ
Add event size to options in a forward protocol
eventのサイズつかって,内部の無駄な処理最適化するやつ
それぞれの説明を詳しく書いてもいいんですが長くなりすぎて誰も読まなくなると思うので,興味のある人は僕に会ったときにでも聞いてください(スライドを読んでもいいですが説明がアレ).
以下が最終発表スライドです.発表は英語でするはずだったんですが,僕のときだけUSの人たちがいなくて日本語で発表OKだったので,日本語が使えることに感謝しながら日本語で発表しました.
感想は?
まずは,Fluentd がいろいろ大変でした(語彙力).そもそも1回くらいしか Fluentd 使ったことなかったのでどうやって使われているか調べるところからはじまり,「あれ,これやばくない???」とか思いながらインターン初日を過ごしていました. @tagmorisさんのスライドにも書いてありますが,Rubyの黒魔術をふんだんに使って書かれていたので非常に読み応えがありました. コードを読む上で,Fluentd ソースコード完全解説 は参考になりました.結構古いので変わってしまったところもありますが,全体の流れを見るにはちょうどよかったです. キッっと睨んでるとわかってきたので大変なのは慣れることだなって感想になりました.
あとは,一番大きい機能の Counter API を merge まで持っていけなかったことが心残りです. 設計をしてレビューのフェーズで大量に時間を使ってしまったのがよくなかったなって感じです. 今の自分ができることと,できないことがはっきりしたのでそういう意味では良かったかなとおもっています.
前々から興味のあったミドルウェア開発を経験できたことは(しかもFluentdで,しかもTDで)とても幸運で,最高の経験だったと思っています. 開催されるかしらないですが,もし来年も開催されならとりあえず出してみると意外とインターン行けるかもしれないので,来年も学生の皆様はぜひ.
まとめ
特にまとめることもないですが,とても刺激的なインターンだったということが伝われば幸いです. 周りは全員超すごい人ばかりだったので,「(業務中自分の力の無さに)おちこんだりもしたけれど、私はげんきです。」という感じです. 社員のみなさん,同期の2人にはとてもお世話になりました.ありがとうございました.
付録1(愉快な仲間たち)
僕の他に2人,インターン同期がいました. 彼らが先に書いたブログがあって僕のより数倍いいのでそちらもぜひ.
@amay382 iPhone7とiOSのことをめちゃくちゃ煽る人(年下なのに優秀でつらい)
トレジャーデータでインターンしてた話 #td_intern - 水底
@takuti オタクかヤンキーかで言えばオタクの人(英語が引くほどうまい)
Treasure Dataインターンにみる機械学習のリアル #td_intern | takuti.me
2人とも機械学習(系?っていうの?あってる?)をやってたので,「インターンでは何やるの?」って聞いたんですけど,丁寧に教えてもらった割に何言ってるよくわからず「すごそう」くらいしか感想がなかったのできっとすごいんだろうなって思ってました.
付録2(食)
牡蠣が苦手だった僕も牡蠣が食べられるようになりました。
#td_intern 最高で具体的には苦手だった牡蠣が食べられるようになるくらい最高 https://t.co/K0BVQ8sfAN
— がんま (@ganmacs) 2016年9月30日
以下、 ログの重要性について真面目にディスカッションしていたときの図です!!!!
高速にメモをとるためのOrg Capture
Org Capture とはOrg-Modeのメモ取りツール(わかりやすく書いてある -> 色々 Org Capture する | Amrta )
以下のように書いておくと(キーバインドはなんだっていい)
(setq org-capture-templates '(("t" "Task" entry (file (expand-file-name (concat org-directory "/task.org"))) "* TODO %?\n %i\n %a\n %T") ("n" "note" entry (file (expand-file-name (concat org-directory "/notes.org"))) "* %?\n %a\n %T") ("r" "reading" entry (file (expand-file-name (concat org-directory "/reading.org"))) "* %?\n %a\n %T"))) (global-set-key (kbd "C-c C-q") 'org-capture)
C-c C-q
と押した時に以下のようなバッファが現れどれかを選択するとメモが簡単に書ける
Select a capture template ========================= [t] Task [n] note [r] reading ------------------------------------------------------------------------------- [C] Customize org-capture-templates [q] Abort
ただ問題があって,たかがメモをとるためにC-c C-q n
とおさないとメモを取れないのはだるすぎる(C-c C-q
の部分は好きに設定できるが最小でも2回必要.しかも画面が勝手に開いて視点がコロコロ変わり本当にだるい)
そこで以下のような関数を作った.これでC-M-=
を一度押せばいきなりメモをかけるようになった.
org-captureの第二引数を上記で記述したorg-capture-templates
のt
(Task)かn
(note)かr
(reading)にすることで指定のテンプレートを使用できる.
(defun org/note-right-now (content) (interactive "sContent: ") (org-capture nil "n") (insert content) (org-capture-finalize)) (global-set-key (kbd "C-M-=") 'org/note-right-now)
Dired でバイナリファイルを開くときに本当に開くか確認する何か
環境
動機
diredでバイナリとか開くときに本当に開いていいか確認してくれる何かが欲しい
— がんま (@ganmacs) 2015, 9月 24
Emacsでは写真やらPDFやらをEmacs内で見れるイッてる機能があります.
しかし,写真やらPDF開こうとすると数秒かかって非常に辛いです.
さらに,Diredを使っているとよく押し間違えてPDFを開いてしまい,数秒待ったあとkill-bufferするみたいなことによくなります.
これが非常に辛いのでなんとかしたいということで書きました.
実際
(defun util/same-ext? (file-path ext) "Check same exntion or not." (let ((file-ext (file-name-extension file-path))) (if file-ext (string= (downcase file-ext) ext)))) (defun util/chomp (str) (replace-regexp-in-string "[\n\r]" "" str)) (setq dired-open-whitelist '("c" "coffee" "clj" "el" "ex" "exs" "go" "h" "hs" "html" "js" "ml" "md" "rb" "yml" "scala" "slim" "scss")) (defun dired/binary? () (let ((cmd (format "nkf -g %s" (dired/filename-at-point)))) (string= "BINARY" (util/chomp (shell-command-to-string cmd))))) (defun dired/filename-at-point () (car (dired-get-marked-files 'no-dir))) (defun dired/directory? () (file-directory-p (car (dired-get-marked-files)))) (defun dired/include-whitelist? (filename whitelist) (if whitelist (or (util/same-ext? filename (car whitelist)) (dired/include-whitelist? filename (cdr whitelist))))) (defun dired-file-open-or-not () "File open if file type is directory or file exntion is in whitelist or file is not binary." (interactive) (let ((ext-lst dired-open-whitelist) (filename (dired/filename-at-point))) (if (or (dired/directory?) (dired/include-whitelist? filename ext-lst) (not (dired/binary?))) (dired-find-file) (if (yes-or-no-p (format "Do you really open? %s" filename)) (dired-find-file)))))
後は
(define-key dired-mode-map (kbd "C-f") 'dired-file-open-or-not)
何をしたか
開くのに時間がかかりそうなファイルを開いていいかどうかを聞くようにしました.
ファイルがBINARYかどうかをnkf
で確認してます.
しかし,毎回nkf
を叩くのは辛いので以下の条件の時はnkf
を叩かずそのままファイルを開いています.
- ディレクトリの時
- whitelistで定義された拡張子のファイルの時
感想
これを書いてたら何故か時間が消えていったが後悔はしていない
emacsからalcでの単語検索を楽にする
環境
コード
(defsubst marked-input () (when (use-region-p) (buffer-substring-no-properties (region-beginning) (region-end)))) (defun search-word-in-alc () (interactive) (let* ((cmd "open \"%s\"") (url (format "http://eow.alc.co.jp/search?q=%s" (or (marked-input) (read-shell-command "word: "))))) (shell-command-to-string (format cmd url)))) (global-set-key (kbd "s-E") 'search-word-in-alc)
ちなみにzshバージョンもある
function search-word-in-alc() { url="http://eow.alc.co.jp/search?q=" open "${url}$1" } alias e='search-word-in-alc'
エスケープ処理とか全くしてないので動きが怪しいこともある気がするけどそこそこ便利!!!