読者です 読者をやめる 読者になる 読者になる

モノノフ日記

普通の日記です

twemproxyのベンチマークを測定してみました

追記

Twitterで計測方法について@bulkneetsさんからフィードバックいただきました。 ありがとうございます。

今出してるベンチの数値はCPU使用時間のベンチになっているため、プロセス間通信は反映されていないためご注意ください。 今度はリモートサーバー環境でBenchmark.pm使わずに試してみたいと思います。

元記事

twemproxyのベンチマークを測ってみました。100000回 set/getをするだけのベンチです。

ベンチマークスクリプト (perl)

ベンチ結果

Benchmark: timing 100000 iterations of memcached, 
redis, redis_pipelining, twemproxy_memd, twemproxy_redis...
memcached:  8 wallclock secs ( 0.85 usr +  2.39 sys =  3.24 CPU) @ 30864.20/s (n=100000)
redis: 13 wallclock secs ( 6.18 usr +  3.04 sys =  9.22 CPU) @ 10845.99/s (n=100000)
redis_pipelining:  9 wallclock secs ( 4.31 usr +  2.24 sys =  6.55 CPU) @ 15267.18/s (n=100000)
twemproxy_memd: 16 wallclock secs ( 0.98 usr +  2.81 sys =  3.79 CPU) @ 26385.22/s (n=100000)
twemproxy_redis: 22 wallclock secs ( 6.86 usr +  3.32 sys = 10.18 CPU) @ 9823.18/s (n=100000)
perl twemproxy_benchmark.pl  28.26s user 196.37s system 79% cpu 4:42.90 total

まとめ

  • twemproxyを挟むと直接接続するときと比べて約20%ほど性能は落ちる
  • 複数台のmemdを管理するコストが無くなるメリットと比べると大した速度低下ではない気はする
  • redisはpipelining使う方がやっぱり速い

twemproxyをmacOSXにインストールするときの注意点

twemproxyはtwitterオープンソースで公開しているmemcached, redisの軽量プロキシです。 ソースコードはみんな大好きgithubで公開されてます。 https://github.com/twitter/twemproxy

infoQとかで紹介されてたりもします。 http://www.infoq.com/jp/news/2012/12/twemproxy

読み方はトゥーエンプロキシ、みたいです。(pronounced "two-em-proxy"とある)

仕事でいじってみる機会があったので手元のmacbookにインストールしたときのメモです。

README.mdの罠

f:id:Kiske:20130930183323p:plain

githubのREADME.mdにインストール手順が書かれているので簡単ですね、 と思いきやGoogle CodeにアップロードされているバージョンはMacOSXではコンパイルが通りません。

checking sys/epoll.h usability... no
checking sys/epoll.h presence... no
checking for sys/epoll.h... no
configure: error: required sys/epoll.h header file is missing

ソースコード読むとepollベースでコンパイルされるぽいのでLinux用でしたという....

masterブランチからインストール

githubのmasterブランチにはOSXでインストールできるパッチが当たっているのでcloneしてきて入れましょう。やり方はREADME.mdのインストールの項の一番下です。

パッチ当ててくれた人に感謝感謝。https://github.com/twitter/twemproxy/issues/2

Gitで「error: xxxxxxxxx does not point to a valid object!」って怒られるときの修正方法

git

GitHub Enterpriseで特定のリポジトリでエラーページが表示が出てるのを修正対応したんですが、書いておかないと忘れる自信があったのでblogged.

状況について

手元にgit cloneしていたリポジトリをpullしようとすると下記のような感じで怒られてました。

% git pull
error: unable to find 60c4f95fb89859e54f5fd2de864393a60fc81a08
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
Your configuration specifies to rebase against the ref 'master'
from the remote, but no such ref was fetched.

Pull Reqeustで作成されたブランチがmasterに取り込まれた後にできるマージコミット(non Fast-Forwardで作られるやつ)のobjectが生成できておらずコミットツリーが辿れないです、ってエラーだと解釈しました。 ただGitHubのWeb UI上ではPull Requestはmerge完了されていました。 しかし、.git/object配下に該当するコミットオブジェクトがない、という無限ループ感。

git ls-remoteで見ても案の定 60c4f95fb89859e54f5fd2de864393a60fc81a08 は見当たらず。。。

GitHub側の設定でDefault Branchをmasterにした状態だとリポジトリのトップページでOctocatが「ooops!!」って叫びながら500エラーを返していましたが、他のブランチに切り替えると普通に表示されてたのでmasterコミットの位置を見失ってしまってる状況に間違いないかなと断定。

f:id:Kiske:20130704120349j:plain

Default Branchをmasterにしたままgit cloneするとエラー。

% git clone xxx.git
error: unable to find 60c4f95fb89859e54f5fd2de864393a60fc81a08
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: recursion detected in die handler

Default Branch切り替えると普通にgit cloneできました。

解決方法

ここから打開方法の解説です。

大筋としてはツリーの歴史上からmasterが見つけられないのでgit push -f origin mew-master:masterでmasterブランチを強制的に上書きしてやれば解決すると推測しました。

問題になるのはnew-masterブランチをどうやって作るか。

まず、この状況になってからはmasterに対して、どのユーザも変更を入れることができていないことを確認しました。GitHub EnterpriseのAdmin toolで閲覧できる操作ログでも確認して、とある時刻から変更が入ってないことを見て一安心。

最新のPull Requestのhead commitを見るとなんと発生時刻直前の状態のブランチ。いきなり当たった。ただ1つ前に出されたPull Reqeust(#1983)の変更は入ってなかったので、これは手で修正しました。(テンプレートファイル2つの修正だけで助かった...) あと、git resetでPull Requestで取り込んで欲しいコミットはログから消してます。

git fetch origin refs/pull/1984/head
git co FETCH_HEAD
git co -b new-master
git reset --hard HEAD~
vi hogehoge # 1つ前のpull reqで取り込まれてた修正を追加

これでnew-masterブランチができました。 最初は単純にgit push -fでmasterブランチを強制的に上書きしようとしたんですがエラー。

% git push -f origin new-master:master
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
Counting objects: 19, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 767 bytes, done.
Total 10 (delta 6), reused 3 (delta 0)
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
error: Ref refs/heads/master is at 60c4f95fb89859e54f5fd2de864393a60fc81a08 but expected 0000000000000000000000000000000000000000
remote: error: failed to lock refs/heads/master
To git@foobar.jp:hogehoge/xxxx.git
 ! [remote rejected] new-master -> master (failed to lock)
error: failed to push some refs to 'git@foobar.jp:hogehoge/xxxx.git'

うーむ。refs/pull/1983/mergeからmasterを辿ろうとしてるところを解消して上げないとダメみたいです。

もう該当のPull Request(#1983)を歴史から無かったことにできないかなーと思ってググってたらQuora先生にそれっぽい記述がありました。 http://www.quora.com/GitHub/What-are-ways-to-delete-a-pull-request-on-GitHub

Pull Requestするときに生成されるrefs配下のペアのコミットを消すといけるかも、ということで消してやりました。new-masterには削除するPull Requestの修正分は反映してるし大丈夫!

% git push origin :refs/pull/1983/head
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
remote: warning: Allowing deletion of corrupt ref.
error: refs/heads/master does not point to a valid object!
error: refs/pull/1983/merge does not point to a valid object!
 - [deleted]         refs/pull/1983/head

わーい、消えました。こんなにサクッと削除できることを知り逆に恐怖。 そしてnew-masterをmasterへ。

% git push -f origin new-master:master
Counting objects: 19, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 767 bytes, done.
Total 10 (delta 6), reused 3 (delta 0)
 * [new branch]      new-master -> master

これで問題解決できました。 git周りのトラブルは影響範囲が大きいので起きて欲しくないですね><

「不格好経営―チームDeNAの挑戦」を読みました

book

もっと経営者向けの本かと思ったら、普通のブログ調で書かれていて読みやすかったです。 7~8割が会社創業から退任されるまで軌跡について書いてて、残りがFAQ集みたいな感じでよく聞かれることをまとめてありました。

僕はお会いしたことはないけれど、この人柄に惹かれていろんな人が集まってきたんだろうなと納得できる本でありました。

不格好経営―チームDeNAの挑戦
南場 智子
日本経済新聞出版社
売り上げランキング: 8

iOS AppとAndroid Appのバナーリンク生成したいとき

それぞれオフィシャルに用意されてたけどわかりにくかったのでメモ。

iOS - Link Maker

http://linkmaker.itunes.apple.com/jp/

Android - Google Play Badges

http://developer.android.com/intl/ja/distribute/googleplay/promote/badges.html

Limechat for Macでjoinやpartメッセージを非表示にする方法

mac版はwebkitレンダリングしてるのでCSSいじれば簡単でした。

使ってるテーマのCSSファイルに次を追加するだけです。 デフォルトのテーマは /Application/Limechat.app/Contents/Themes にあります。

下の例ではjoin, quit, mode, part, nickを表示しないようにしてます。

.line[type=join] { display:none; }
.line[type=quit] { display:none; }
.line[type=mode] { display:none; }
.line[type=part] { display:none; }
.line[type=nick] { display:none; }

だいぶスッキリしました!!1

Jenkinsで実行ユーザをjenkins以外にしている場合でアップデートするときの罠

深遠な理由でJenkinsの実行ユーザをデフォルトのjenkins以外に設定しているケースでJenkinsのアップデートを行うと嵌まりやすい罠がありました。環境はCentOS 6.3です。

sudo yum update jenkins

yumでアップデートするとパッケージは更新されるんですが起動しなくなります。

sudo /etc/init.d/jenkins start
Starting Jenkins [ OK ]
sudo /etc/init.d/jenkins status
jenkins が停止していますが PID ファイルが残っています

なんだpidファイル残ってるのかーと /var/run/jenkins.pid を消そうとするとファイルが存在しておらず詰みます。

原因はpidファイルではなくてアップデート時に /var/log/jenkins, /var/cache/jenkins が jenkinsユーザにchownされてしまうからでした。起動スクリプト(/etc/init.d/jenkins) を読んでようやくわかりましたよ...

sudo chown -R foobar:foobar /var/cache/jenkins
sudo chown -R foobar:foobar /var/log/jenkins

Jenkins自体の実行ユーザはjenkinsが無難な気がします。Jenkinsのプロジェクト内のビルド実行は普通のシェルスクリプトなので他ユーザで実行するように書けば問題ないかと!