すぐに子供の写真を見れるGoogle Chromeの拡張作った。
※元ネタはこちらです
http://soh335.hatenablog.com/entry/2013/02/10/011039
http://hisaichi5518.hatenablog.jp/entry/2013/02/01/003820
soh335さんのリポジトリをforkし、
DropboxAPIを利用してDropbox内の写真を表示するように改造してみました。
この拡張でやれること
最初は後者をやりたくて始めたんですけど、DropBoxAPIの仕様によりペンディング中です。
理由は後述。
準備(アプリ編)
ダウンロード
適当なフォルダで以下のコマンドを実行して下さい。
git clone https://github.com/toritori0318/chrome-tumblr-tile.git
OAuthライブラリダウンロード
oauth.jsとsha1.jsを同じフォルダにダウンロードします。
https://oauth.googlecode.com/svn/code/javascript/
準備(Dropbox編)
Dropboxアプリ登録
以下のURLからCreateAppします
https://www.dropbox.com/developers/apps
App key / App secret 取得
アプリケーション情報から "App key" と "App secret"をメモしておきます
アクセストークン取得
APIを使うためのアクセストークンを取得します。
Web上で取得する方法が見つからなかったので、
今回はPerlで以下のような簡単なスクリプトを作って実行しました。*1
https://gist.github.com/toritori0318/10553050
実行するとOAuth URLが表示されるので、
ブラウザでURLを表示してアプリの認証を行い、
コンソールに戻ってエンターキーを押すとトークンが表示されます。
これをメモっておきましょう。
準備(写真編)
準備(Chrome編)
Chromeでタブを開く
内部説明
TumblrAPIとDropboxAPI仕様が異なる部分があるので
中でやっていることを少しだけ説明します。
- Dropbox metadata APIでフォルダ内のファイル一覧取得
- 20ファイル分のURLをDropbox thumbnail APIで取得し、blobデータをimageに変換し、DOMツリーに追加
- 下部にスクロールした時に、次の20ファイルに対して 2. を実行
DropboxAPIにはページングという気の利いた機能が無く、
フォルダ内のオブジェクトをまるっと取得する手段しかありません。
そのため、一気に処理してしまうとフォルダ内全部のサムネイルを取得してしまうので
ブラウザに表示している部分だけを少しずつ画像取得するようにしています。
Camera Uploadsをストリームっぽく表示してみたかった
元々の動機は
「奥さんが撮っている写真をリアルタイムでブラウザに表示出来たりしたら面白いかなー」
というので書き始めたんですが、DropBoxAPIにページングが無いため
「Camera Uploadsフォルダ」が膨れ上がると
タブを開くたびに大きなネットワークアクセスが発生してしまいます。
それがイマイチっぽい感じがしたので実装を断念しました。
ただ、今の仕様でも実装してみたら全然満足しているのでこのままでもいいかなーと思ってます。
まとめ
Chromeのタブを開くだけで幸せな気分になれます。最高。
子供でなくても、ペットや恋人の写真など表示しても捗るのではないでしょうか!
*1:cpanm WebService::Dropbox しておきましょう
microインスタンスはlimitかけると大きくパフォーマンスが向上する(※再追記あり)
※2014/07/02 T2インスタンスタイプとの比較 を追記しました。
※2014/03/13 他インスタンスタイプとの比較/m3.mediumの検証 を追記しました。
こちらの記事の二番煎じです。
cgroupで、お手軽CPU使用率制限
なるほど。
リソースにLimitかけるとstealを防げるためパフォーマンスも上がるというわけですね。
どのくらい変わるのか実験してみました。
cgroup前準備
sudo yum install libcgroup sudo chkconfig cgconfig on sudo service cgconfig start
cgroup設定
上記参考URLとほぼ同じ設定です。
実行時はcpu.cfs_quota_usを変動させて比較してみました。
sudo vi /etc/cgconfig.conf # 以下を追加 group limittest { cpu { cpu.cfs_quota_us = 250000; # Max25% cpu.cfs_period_us = 1000000; } cpuacct { } } # 変更後はリスタート sudo service cgconfig restart
定常的に使う時は、memory.limit_in_bytes なども設定して
メモリもlimitかけると良いかもしれません。
比較コマンド
perlのビルドの時間を比較してみました。
リミットなしバージョン
time perlbrew install perl-5.18.2
リミットありバージョン
time cgexec -g cpu:limittest /root/perl5/perlbrew/bin/perlbrew install perl-5.18.2
結果
- | real | user | sys |
---|---|---|---|
リミットなし | 186m59.721s | 127m54.352s | 51m52.487s |
リミットあり(Max25%) | 90m8.645s | 15m4.317s | 5m31.501s |
リミットあり(Max30%) | 75m3.421s | 15m1.468s | 5m24.844s |
リミットあり(Max40%) | 87m26.738s | 23m40.645s | 8m50.737s |
リミット無しでsteal発生しまくりの時はおよそ3時間かかっていたのが、
リミットあり(Max30%)だと1時間15分ほど。2倍以上速い!!
※以下引用
いくつかの調査をした結果,
Amazon EC2 Microインスタンスの挙動について
・直近の100秒のCPU使用率が20%を超えている場合は低速モードに移行する
・低速モードはCPU使用率の97%が使えない状態(steal)になる
とあるので、20%ギリギリ超えるくらいがちょうどいいかなと予想していましたが
実際には30%が一番パフォーマンスが良かったです*1
vmstatでstealの値も見ていたんですが、
Max40%だと結構stealが発生していて、
Max30%の場合ごくごくわずかにstealが発生するくらいでした。
常にCPUMaxをつかう処理があるわけではないと思うので、
20%よりも少しばかり高めに設定したほうが
効率が良いのかもしれませんね。
まとめ
cgroupで制限するとmicroインスタンスでは大幅なパフォーマンス向上が見られました。
大きいビルドなど行うときには必須ではないでしょうか!
※追記 他インスタンスタイプとの比較
smallとの比較があったらよいのでは、というコメントを頂いたので
ついでにインスタンスタイプ別に比較してみました。
m1.smallだけでなく、グループ毎の下位クラスも一緒に比較してみました。
- | real | user | sys |
---|---|---|---|
t1.microリミットありver | 75m3.421s | 15m1.468s | 5m24.844s |
m1.small | 46m3.623s | 29m54.188s | 10m54.853s |
m1.medium | 25m33.974s | 15m17.969s | 5m0.599s |
m3.medium | 31m42.804s | 18m45.818s | 7m47.473s |
c1.medium | 25m1.527s | 15m16.129s | 5m34.785s |
c3.large | 16m41.832s | 9m31.712s | 3m25.633s |
c3は予想通りの早さですね。
他のインスタンスも軒並み予想通りですが、一つだけ気になる結果があります。
m3.mediumインスタンスです。
m1.mediumとm3.medium
公式のインスタンスタイプを見ると
以下のようになっています。
- | ecu | vcpu |
---|---|---|
m1.medium | 2 | 1 |
m3.medium | 3 | 1 |
あれれ、数値上はm3.mediumの方が良さそうですね*2。
なぜm1.mediumの方が速いのでしょうか?
ビルド時のスナップショット
m3.mediumのビルド時のvmstatのスナップショットです。
stealが40-50%ほど発生しています。
m1.mediumはというと、stealの発生はありませんでした。
予想:CPU共有タイプ?
公式ドキュメントからは確認出来なかったのですが、
おそらくm3.mediumもm1.smallと同じように
「CPU共有型なのではないか」と予想しました。
詳しくは以下のブログをご覧頂くと良いです。
AmazonEC2 m1.smallのCPU配分
http://php6.jp/linux/2012/01/20/amazonec2-m1-small/
vmstatの推移がm1.smallとm3.mediumで同じような挙動をしているので
ほぼ間違いないのではないかと思います。
m3.largeも試してみる
本当は上記インスタンスだけ比較して終わろうと思ったのですが、
m3のグレードを一つ上げたらstealしなくなるか、を確認してみました。
- | real | user | sys |
---|---|---|---|
m3.large | 17m1.667s | 10m1.062s | 3m21.857s |
ビルド時のスナップショット
stealが消え、ほぼ公式と同じような性能が出ているように見えます*3。
やはり、stealが発生するのはm3.mediumだけのようです。
追記:まとめ
単に性能比較して終わる予定だったのですが、
m3.mediumインスタンスで新たな発見がありました。
m1.mediumと比べて、
「m3.mediumの方が安いし性能もいいしこれでいいじゃんヒャッハー!!!」
と思っていましたが、mediumだけでみると「m1.mediumの方が速い」という結果でした。
ほげぇ。
匿名さん、コメントありがとうございました。
再追記:T2インスタンス
バーストありとバーストなしで追試しました。
バーストあり時は t2.micro/t2.small/t2.medium であまり変わらなかったので
どちらもt2.microの値です。
- | real | user | sys |
---|---|---|---|
t2.micro(バーストあり) | 14m46.383s | 8m53.064s | 0m26.884s |
t2.micro(ベースライン:10%) | -(※注1) | -(※注1) | -(※注1) |
バースト時にはc3インスタンスと遜色ないですね。
また、以下はt2.microのバーストあり時の残高クレジットです。
30-22で、およそ8クレ消費しているようですね。
※注1
【悲報】ベースラインビルド、なんと
2週間回し続けても一向に終わる気配がありませんでした!!!
(途中で強制終了しました)
もしかしたら実測としてはベースラインを大きく下回っているのかも…
*1:途中ネットワークアクセスなども発生していたり、というのもあると思います
*2:自分もこの辺りの性能比較を過去記事に書いています http://d.hatena.ne.jp/toritori0318/20140203/1391445479
*3:c3.largeと比較して
チャットを面白おかしくするおもちゃ箱
Skype や IRCなど、チャットツールは
サービス開発のコミュニケーションツールとしては無くてはならないものである。
しかし時として、場の空気が重くなることもあるだろう。
そんな時、一筋の光をもたらすようなbotがいたなら。。。
時に笑いを提供し、時には場の空気を読まない悪戯小僧のような存在。
そんなライブラリ書いた。
リポジトリ
https://github.com/toritori0318/p5-toy
基本的には「おもしろ画像URL」をランダムに返すだけのライブラリなので、
どのチャットツールでもご利用可能です。
unazusanを利用していれば、exampleをコピペするだけですぐに投入できるでしょう。
プルリクも大歓迎!
画像取得用サービス一覧
*1:エロ的な意味で
M3インスタンスを使わない手はない
最近、また新たにEC2のインスタンスサイズが増えましたね。
【AWS発表】M3インスタンスの新サイズおよび新機能 + EBSの値下げ + S3の値下げ
M3インスタンスはM1インスタンスの後継にあたる汎用インスタンスです。
今回新たに追加された m3.medium / m3.large は価格帯も性能もバランスよく、
非常に使いやすいインスタンスなのではないでしょうか。
本題
ふとM1/M3の料金表を見比べてみたんですが、
同じグレードで比較するとM3の方が料金安いんですよね。
しかも数値上はM3の方が性能も高そうです。
比較表にしてみましょう。*1 *2
インスタンス | vCPU | ECU | RAM(GB) | インスタンスストレージ (GB) | EBS 最適化 | ネットワークパフォーマンス | 時間あたりの料金(東京リージョン) |
---|---|---|---|---|---|---|---|
m3.medium | 1 | 3 | 3.75 | 1 x 4 SSD | - | 中 | $0.171 |
m1.medium | 1 | 2 | 3.75 | 1 x 410 | - | 中 | $0.175 |
インスタンス | vCPU | ECU | RAM(GB) | インスタンスストレージ (GB) | EBS 最適化 | ネットワークパフォーマンス | 時間あたりの料金(東京リージョン) |
---|---|---|---|---|---|---|---|
m3.large | 2 | 6.5 | 7.5 | 1 x 32 SSD | - | 中 | $0.342 |
m1.large | 2 | 4 | 7.5 | 2 x 420 | 可 | 中 | $0.350 |
インスタンス | vCPU | ECU | RAM(GB) | インスタンスストレージ (GB) | EBS 最適化 | ネットワークパフォーマンス | 時間あたりの料金(東京リージョン) |
---|---|---|---|---|---|---|---|
m3.xlarge | 4 | 13 | 15 | 2 x 40 SSD | 可 | 中 | $0.684 |
m1.xlarge | 4 | 8 | 15 | 4 x 420 | 可 | 高 | $0.700 |
まとめ
M1シリーズ、大容量のインスタンスストレージが欲しい以外は
選択する意味があまり無さそうですね。
これはもう「M1を捨ててM3を使え」というAmazonさんからのメッセージと受け取って
M3を使いまくりましょう〜
*1:表はこちらから抜粋させて頂いております http://aws.amazon.com/ec2/instance-types/ http://aws.amazon.com/ec2/pricing/
*2:比較する対象のないm1.smallとm3.2xlargeは除外しています
pip1.5に注意
とある日、素のインスタンスにchef走らせたらpip installで何故かエラーになりました。
デプロイ周りで特にレシピ変更してないし全く身に覚えがない。。。
差分chefインストールだとpipエラー出ないし何でだー?とトレース追ってみると
argparse==1.2.1
でエラってる。そんなバージョンないよって言われる。
pipのバージョン
いろいろ調査した結果、pipのバージョンが怪しいということになって
確認してみると確かに違う。エラーが出るのはpipバージョン1.5だ。
どうやらpip1.5では外部にホストされているモジュールは
デフォルトでインストール出来なくなっているようである。*1
回避策
pip installのオプションで
--allow-all-externalを付けるとうまくインストールされました。
--allow-external PROJECT_NAME で個別にURLを指定することもできるようです。
ということで
pipの最新バージョンを使うと
デフォルトの挙動が変わってしまうので注意しましょう、というお話でした。
他にもいくつか下位互換が失われている変更があるようです。
http://www.pip-installer.org/en/latest/news.html#id1
つかリリース日2014/1/1って。。。
*1:確かに、argparseの1.2.1だけgooglecodeに置かれてる。https://pypi.python.org/simple/argparse/
2013年振り返りと2014年
年末年始バタバタしてたので今頃振り返ってみます。
仕事
DevOps頑張ってた。
監視自動化とか、開発運用共通化とか。
改善前は各モジュールで独自の開発フローや秘伝のタレ化したデプロイツールなど、
担当者がいないと誰も管理できなくなってしまうという
「担当者SPOF」になってしまっていて、
それを改善したいなーと思い
「vagrant + chef + cloudformation」という構成で
インフラ構築/運用/開発フローを共通化するためにいろいろ頑張ってた。
現在はこれを拡張して
- AMIの作成
- image-idを自動でcloudformationのテンプレートに適用
- そのままcloudformationのstack作成/更新/削除
という一連のフローを同じrakeタスクで実行できるようにした。
その結果、どのシステムでも全く同じ手順で
- デプロイ
- インフラ構築
- クラスタ構築
- スケールアウト/スケールイン/スケールアップ/スケールダウン
などが実現できるようになった。
これ実現出来たのは地味にでかいと思ってる。
趣味コーディング
ひょんなことからCPAN Authorになれた。嬉しい。
しかし書きたかったコードはたくさんあったんだけど
それほど書けてなかったような気がする。
プライベート
上の子が幼稚園に入った。
いまだに朝嫌がることはあるが、実際に登園すると普通に楽しんでるようなのであんまり心配してない。女の子にモテてるらしい。くやしい。
下の子はどんどんかわいくなってる。うへぇ
あと結婚10周年でした。美味しいもの食べた。
2014年
仕事関係ではソケットサーバパワーアップさせないと辛いなーって感じになってきてるので
本気でチューニング始める予定。予定は未定。
あと気になってるソリューションがたくさんあるので
徐々に勉強復活させたい。
以下とか。イミュータボー?
- Docker
- Serf
- Mesos
- Graphite
- Sensu
yogaコマンドも追加機能したいタスクがどんどん溜まってきてるので消化したい。
やりたい。やらねば。
nginx-lua-moduleでLuaスクリプト書いてみた
プロダクトでWebサーバ上の現在時刻出したい要件がありました。
これぐらいの処理ならアプリケーション介さずともnginxだけでやりたいですね。
現在時刻ヘッダーにつけるならnginx標準機能で出来そうなんですが、
深淵なる理由からコンテンツとして欲しいとのこと。
今後、Nginx+Lua試してみたいなーという要件もありましたし、
せっかくなのでこの機能をLuaスクリプトで書いてみることにしました。
nginxレシピ
opscodeのnginxクックブックにはluaをインストールするレシピもありました。
しかし、例のごとくそのままでは動かせなかったので
一部オーバーライドしたクックブックを書いてみました。
AWSの生AMIにこれをそのままプロビジョニングするとNginx+Luaが起動することを確認しています。
https://github.com/toritori0318/chef-nginx-lua-sample
直したところ
recipes/lua.rbにパッチを当てたのと、
recipes/source.rbにluaをインストールする処理を差し込んだくらいです。
ちなみにcjsonを入れているのは、今回json形式でレスポンスさせたかったからです。
Luaを動かすだけであればcjsonを入れる必要はありません。
サンプルアプリ仕様
サンプル実装
/etc/nginx/sites-available/lua_current_time
nginxのコンフィグです。
特に語るところはありません。
# Lua soライブラリのパス指定。今回はcjsonのため(ファイルパターンも指定が必要らしい) lua_package_cpath "/usr/local/lib/lua/5.1/?.so"; server { listen 80; access_log /var/log/nginx/access.log; location /current_time { # 外部Luaスクリプト読み込み content_by_lua_file /etc/nginx/lua/current_time.lua; } location / { default_type 'text/plain'; # コードもそのまま書ける content_by_lua "ngx.say('Hello,lua!')"; } }
/etc/nginx/lua/current_time.lua
パラメータを受け取ってゴニョゴニョしています。
特に語るところはありません。
local cjson = require "cjson" local ctime = "" local args = ngx.req.get_uri_args() if args.df == "epoch" then ctime = os.date("%s") else ctime = os.date("%Y-%m-%dT%H:%M:%S %z") end if args.rf == "json" then ngx.header.content_type = "application/json"; ngx.print(cjson.encode({current_time = ctime})) else ngx.header.content_type = "text/plain"; ngx.print(ctime) end
非常に簡単ですね。
ベンチマーク
abしてみました。
コマンドパラメータはこんな感じです。
ab -n 20000 -c 2 http://127.0.0.1/xxxx
/ (Hello Lua)
Server Software: nginx/1.4.3 Server Hostname: 127.0.0.1 Server Port: 80 Document Path: / Document Length: 11 bytes Concurrency Level: 2 Time taken for tests: 2.018 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 3060000 bytes HTML transferred: 220000 bytes Requests per second: 9912.15 [#/sec] (mean) Time per request: 0.202 [ms] (mean) Time per request: 0.101 [ms] (mean, across all concurrent requests) Transfer rate: 1481.02 [Kbytes/sec] received
/current_time
Server Software: nginx/1.4.3 Server Hostname: 127.0.0.1 Server Port: 80 Document Path: /current_time Document Length: 25 bytes Concurrency Level: 2 Time taken for tests: 2.339 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 3340000 bytes HTML transferred: 500000 bytes Requests per second: 8549.87 [#/sec] (mean) Time per request: 0.234 [ms] (mean) Time per request: 0.117 [ms] (mean, across all concurrent requests) Transfer rate: 1394.36 [Kbytes/sec] received
/static/index.html(静的ファイル配信。このファイルは手動で作りました)
Server Software: nginx/1.4.3 Server Hostname: 127.0.0.1 Server Port: 80 Document Path: /static/index.html Document Length: 6 bytes Concurrency Level: 2 Time taken for tests: 1.942 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 4680000 bytes HTML transferred: 120000 bytes Requests per second: 10298.39 [#/sec] (mean) Time per request: 0.194 [ms] (mean) Time per request: 0.097 [ms] (mean, across all concurrent requests) Transfer rate: 2353.34 [Kbytes/sec] received
静的ファイル配信よりわずかに落ちますが十分早い。
Nginx+Lua、環境設定が若干面倒ですが、
上記クックブックを使うと一発で環境作れますし、
Luaスクリプトもお手軽に書けそうなので試してみてはいかがでしょうか〜
(゚Д゚)オLua!オLua!
*1:※追記 openrestyを使うと楽できるようです! http://openresty.org/