コマンドラインを複数回実行して実行時間を計測するツールを書いた

walf443/benchcmd · GitHub

なんか最近ツール系のやつを趣味で高速化したりしていて、PR投げるときに速くなったよと説明するときに手元で何度か計測して、平均値とか調べるのがめんどいなと思って、複数回実行して平均/標準偏差を表示してくれるツールを作った。

もっと定番のがあるような気がするけど、あんまり聞いたことがない。

Usage of benchcmd:
  -n int
          number of times to run (default 10)
  -summary
          only output summary result
$ benchcmd -n 10 'go version'
run "go version"
15.711435ms
19.42685ms
19.967876ms
24.896109ms
19.557516ms
21.698995ms
16.499163ms
22.28795ms
23.461732ms
18.743192ms
count:  10 times executed
avg:    20.225081ms
stdev:  2.634089ms

importするだけですべてのHTTP通信をログる

今回のisuconに対応できなかったので、作ろうと思ったけど、id:motemenさんが既に作ってた

昔見た記憶があったのだけど、すっかり記憶から忘れていた。

motemen.hatenablog.com

何msぐらいかかったかとかは出てこないので出力できるようにしてみたが、拡張方法が互換性がないのでmergeしてもらえないかもしれない。

github.com

とりあえずmergeされなくても使えるように整えておいた。

github.com

isuconで惨敗しました

isuconでチームフリー素材として参加しました。54,868点で8位でした

今回は、開発環境の構築で色々とてこずりました。

DBがpostgresqlだったので、手元で構築しようとしていたときに、brew updateしてしまい、postgresqlのdatabaseのバージョンが一致しないので起動できないという状態になってしまいました。それで色々やっていると、手元のdatabaseを壊してしまってちょっと復旧は諦め、3台のうち1台を開発サーバーにしました。

deployできるようにしようとしていたのですが、手元からsshはとおるのですが、サーバー間でsshがつながらない状態だったので、iptablesなどを疑ったのですが、わからず、仕方なく、手元へbinaryをscpして、remoteへscpしなおすshell scriptを書いてなんとかしました。 sshがつながらなかったのは、懇親会で聞いたところ、hosts.denyの設定がされていたから、だったらしいです。

ようやく色々できるようになったのが、13:30ごろでだいぶ出遅れてしまいました。

serviceを取得する処理がN+1クエリだったので、INを使うように書き換えました。(追加がないのはその時点でわかっていたので、他のチームのようにハードコーディングするべきだった)

あとは他の人へ指示を出しつつ、curlでどのAPIがどのぐらいキャッシュできそうか、などを確認していました。

tenkiは最後まで悩んでいたのですが、curlを連打していると同じ結果が返ってくるので数秒ならいけそうと試してみたらtestが通ったので、徐々にあげてみて、2秒で落ちつきました。

グローバルIPしか持っていなかったので、どうやって複数台で分散させようか悩んだのですが、前回のようにログイン後のRedirect時に別のIPへRedirectさせたらどうか、ということでやってみましたが、test部分でfailしていたので、諦めてnginxでグローバルIPを直でproxyするのを試したりしました。

ただ、DB部分をグローバルIPでアクセスさせるという発想はなかったので、結局諦めて1台でがんばることにしました。

色々知識不足などで効率的に動けなかったので、復習して次回に備えようと思います。

2行書きかえるだけでSQLをログに出力できるようになるgo-sql-tracerを作りました

isucon予選中に、SQLを出力したくなったのだけど、ふとgithub.com/shogo82148/go-sql-proxyを使ってみようとしてとりあえず簡単に使う方法が書いてなくて少し使い方を調べるのに苦労したので、isuconで時間のロスなく使えるようにそのwrapperを書きました。

package main

  import (
    database/sql
    "github.com/go-sql-driver/mysql" # load driver before load go-sql-tracer
    _ "github.com/walf443/go-sql-tracer"
  )

  func main() {
    db, err := sql.Open('mysql:trace', dsn)
  }

ポイントは、

  • 元々使っていたドライバ名に":trace"とつけること
  • go-sql-driver/mysqlをimportしたあとに、importすること

です。

今database/sqlに登録されているドライバ一覧から、go-sql-tracerのinit内で、':trace'をつけてドライバを登録しているので使いたいドライバの後でimportする必要があります。

go-sql-proxyはカスタマイズも柔軟にでき、非常に素晴らしいライブラリですが、カスタマイズしなくてもいいのでとりあえずSQLのログみたい、というときは非常に便利かと思います。

github.com

じわじわチャットへ通知する

なんかのバッチを実行していて、それが出力するログをじわじわチャットへ通知したい。(そのバッチはそれなりに時間がかかるものとする)

何も考慮しなければ、たとえばslackであれば、

# #!/bin/bash
# notify_chat.sh

exec tee >(while read line; do curl -s --data '$line' $SLACK_ENDPOINT -o/dev/null; done

みたいにやれば、

$ ruby batch.rb | notify_chat.sh

で毎行slackさんへ通知してくれる。


このやり方だと、場所によってはAPIをどばっと叩いてしまって負荷をかけてしまったりするので、1秒間の出力はまとめてわたせるようにするコマンドthrottleというものを書いてみた。

  $ ruby batch.rb | tee >(throttle -interval 1s "curl -s --data '%%DATA%%' $SLACK_ENDPOINT -o /dev/null")

みたいにやると、1秒間の出力はまとめてcurlコマンドへ渡してくれる。1秒間の出力は、%%DATA%%の部分が置きかえられて実行される

$ go install github.com/walf443/throttle

でインストールできる

ソースは、

github.com

Chrome拡張でCocoaPodsのPodfile.lockのdiffからも各ライブラリの変更へ飛べるようになった

昨日だしたやつが、CocoaPodsのPodfile.lockのdiffからもclickできるようになりました。

また、Pull Requestのページのdiffで発動しなかった問題を修正しました。
権限まわりを変更している関係で、既にインストールした人はv0.0.2にアップグレードされた人は、無効になっていることがあるので注意してください。

Github Library Changes - Chrome ウェブストア

f:id:walf443:20150803075554p:plain

github.com

関連

walf443.hatenablog.com

githubのGemfile.lockやpackage.jsonのdiffからそれぞれのライブラリのdiffへ飛べるChrome拡張を作った

ChangeLogのファイルはプロジェクトにあったりなかったりなので、githubリポジトリのタグ間のdiffへクリックでいけるようにしてみた。
これでbundle updateとかしたときにざっくりどういう更新があったのか確認ができる。

現在は、Gemfile.lockのdiffと、package.jsonのdiffに対応している。

Github Library Changes - Chrome ウェブストア

f:id:walf443:20150803075554p:plain

github.com