Subscribed unsubscribe Subscribe Subscribe

ダメ人間オンライン

あまり信用しないほうがいい技術メモとか備忘録とかその他雑記

TokyuRuby会議09でLTしてきた

TokyuRuby会議に初めて参加してLTしてきました。

LTした結果多くの方が投票してくれてLT王となりました!やったぜ!!

いただいたLT王Tシャツ
f:id:dameninngenn_owata:20150904030203j:plain

副賞(?)のガオガイガーの日本酒!!
f:id:dameninngenn_owata:20150904030650j:plain

LTのタイトルは「第一回 チキチキ 独断と偏見と狭い観測範囲の中から選ぶコミットログ選手権」というやつで、タイトルからネタLTの匂いがプンプンする感じですがその通りの完全なネタLTでした。

f:id:dameninngenn_owata:20150904031231p:plain

LTの冒頭でも言った通りスライドは公開しないです。すいません。今回のLTは結構しゃべりで大部分フォローする感じの発表だったので、資料だけ見てもたぶんおもしろくないですし。。

で、TokyuRuby会議09 - Regional RubyKaigi を見てもらえればわかると思いますが、私以外のLTはとてもためになる内容のものばかりで酔ってない時に聞きたいと思うようなLTばかりでした。
そんな中こんなネタLTで応募しちゃってやっちゃったかなーとすごく不安な気持ちになってたんですが、懐が深く、受け入れてくれてその上おもしろかったよと言ってもらえてとても嬉しかったです。

飛び道具を使って賞をもらった感は否めないので機会があれば今度はもう少しちゃんとした内容のLTをやりたいですね。

スタッフの皆さん、参加者の方々、最高のイベントをありがとうございました!


末路

YAPC::Asia Tokyo 2015に行ってきた

今年は絶対にトークやるぞオラァ!と思って応募したけど残念ながら落選。納得の落選だったので仕方がない。
なので今年も普通に参加してトークを聞いてきました。

トークが終わって移動中にトイレ行ってたら次行こうと思ってたとこが既に満席で入れないみたいなケースがあったけど、特定のトークだけでなく色んなトークで発生してたようなので全体的に大盛況だったということでしょう。こればっかりは仕方がない。

で、一日目のLTをヘラヘラしながら見てたら hiratara さんのLTで過去の自分のLT(Werl)の内容が取り上げられてて、嬉しびっくりしすぎて何もまともなリアクションができなかった。

次の日の「YAPCあるある」っていうトークセッション中でも yusukebe さんがWerlについて言及してくれてたようでタイムラインでもちらほら見かけた。

ただあのLTは五年も前のペラッペラの時の自分なのでこっ恥ずかしい気持ちはすごいあるw
あのLT見て笑って喜んでくれる人もいれば否定的な人ももちろんいて、否定的な意見も全く的外れではないので見かける度自分の豆腐メンタルがグシャァってなるけどこうして五年経ってもなお覚えてくれてたり話に取り上げてくれる人もいてとても嬉しいので堂々としてようと思う。

で、あのイメージがでかすぎるのでちゃんとした本編での有益なトークをしなければならない!!!!!みたいな気持ちが大きくなってきてたけど残念ながらラストチャンスを逃しそれは叶わなかった。仕方がない。
その分集中してトークも聞けたし良い感じにダラダラと過ごせることができたので最高でした。

参加者及び運営の皆さんお疲れ様でした。
そしてYAPC期間中話してくれた方々ありがとうございました。とても楽しかったです。

ISUCON2014予選に参加してきた

念願のISUCONに初参加してきた。
チームメンバーは同僚のaskaさんshiya氏で、「西日本世界チャンピオン*1」というチーム名で参加した。

予選までの準備

まずチーム名を考えるのに一ヶ月近く時間をかけた。最終的に満足のいくチーム名になって100万とった気になってた。

他には事前に準備しておいたほうがいいものや、どういう方針でやっていくかなどをチートシートとしてまとめて(githubのprivate repositoryで管理)メンバー内で共有した。これは当日も役に立ったので良かった。

特にshiya氏は普段objective-cを書いててサーバーまわりのことはわからないことだらけとのことだったので(しかも我々が選択する言語はPerlだ!)、事前に準備しておけばできるような作業(アクセスログ解析とかhttpdからnginxへの入れ替えとか)についてもチートシートにまとめておいて確認してもらった。

予選当日

まず心の拠り所として
f:id:dameninngenn_owata:20141003032100p:plain
を共有してた。これも共有しておいて良かった。

開始直後は予め決めていた進め方通りに進めた。

  • 俺がAMIを起動して一旦みんなでそこへログインする
  • 他の皆が環境やapplicationを確認してる間、俺が必要なもの(webapp, my.cnf, nginx.conf, etc...)をgitで管理できるようにしてprivate repositoryへpush
  • デフォルトで動いてるrubyのアプリケーションを止めてperlで起動するよう変更
  • 各種再起動スクリプト等を準備
  • 環境が整ったらその状態からAMIを作成してチームメンバーに共有して、各メンバーはそのAMIを元にインスタンスを立ち上げて自分の環境で作業する

ここまでは割りとスムーズに進んだ。もちろんインスタンス起動直後にベンチマークを走らせてお約束の

をやってゲラゲラ笑ってた。

ちなみにベンチマークは比較がしやすいよう17時ぐらいまでは--workload 1しばりで行こうという方針にしてた。

各自確認した情報を口頭やIRCで共有しつつどこから取り掛かるか目星をつけていった。

  • proxyからstaticファイル配信したい
  • appへの接続をTCPからUNIX domain socketへ変更したい
  • session storeをファイルからメモリへ
  • memcachedいれとくかー
  • 気まずいSQLたくさんあるのでなんとかする
  • まず明らかindex貼ったほうがいいとこは貼る
  • mypageでアクセスするたびusersからSELECTしてるけどどうかなー

最初挙げたのはこれぐらいだったと思う。

そこから各自これやるわーって言ってやり始めた。
俺とaskaさんはアプリケーションまわりとか気になったとこからやり始めて、shiya氏にはまずnginxの設定変更してstaticファイルをnginxから配信してもらうようお願いした。

リポジトリの運用ルールとしては、

  • まずブランチを切って作業してそのブランチでベンチマークを走らせる
  • masterにマージした時もベンチを走らせてスコアをタグとして記録

という風にした。途中から案の定ぐだったけど、ぐだった場合はこのルール気にせず本質的な対応に注力しようというのも共有してたので「おい!このマージスコアいくつやねん!!タグついてへんぞオラァ!!!!」みたいなケンカには発展しなかった。

で、ここまではわりかし順調やったけどここから雲行きが怪しくなってきた。
なんかしらんけど(←)ベンチマークのfailカウントが0じゃなくなった。
特に大した対応してないはずやのに突然。なんか変更加えるたびにベンチ走らせて確認してたはずやのに突然。
なんか記録してない意図せずやったことがあるんやろうけどhistory遡ったりcommitログ遡ったりしてみたけど全く改善しない。
masterとして扱っていたインスタンスでは同じgitのリビジョンでも再現しなくてほんとにわけわからん状態になった。

結論から言うともちろんなんかしてたわけで原因はあったわけやねんけど、それが判明した頃には既に2時間ぐらい経過してた。
askaさんがこれが原因じゃね?って言ってくれて「いやいやまさか、、、うわぁああああああああ」みたいに判明した。askaさんの時間も奪ってしまったしほんと死ぬしかない感じだった。

いやいや違うんですよ。だって(言い訳は削除されました)

で、ここで完全に壊されて次の対応も何かハマって死にそうになって気がついたらえらい時間経っててご飯も食べてないから頭回ってなくて昼飯買いに行ったのが3時か4時ぐらいだったと思う。

そこから慌ててindex貼ったり、ログインに失敗したカウントはip基準とuser_id基準で別テーブルにしてそっちでカウントとってったほうが楽そうってことでそうした。
ここらへんでスコア13000(--workload 1)ぐらいだった。そういえばスコアの送信最初と最後のほうしかしてなかった。

ここで気づいたのが別テーブルにしたらinit時にダミーでinsertしてるデータ分も同様に最初に対応しとかないとダメってことでその対応もした。この初期データ対応は結構難航した。

failure_countを上のように別テーブルで管理するんじゃなくmemcachedとかでincrしてけばいいかなって話も出たけど、一度ログインに成功したらそこからのカウントを元々とるようになってたしmemcachedでincrした場合に途中でサーバー再起動かかってデータ吹っ飛んだら正しくカウントができないってことでその案は没になった。
一度BANされれば状態は変わらないけど失敗カウントが増えてる段階ではそのカウントも保持しておかなければいけない。

それ以降もなんかやろうとしてたけどベンチマークのfailが増えたりして中々うまくいかんくて気づいたら17時とかになってたのでそれなりのスコアで送信しとかないともうまずいってことに気づいた。

その時点でのmasterブランチは安定してなかったので過去のスコアがよさそうなブランチでworkloadの値変えながらベンチとった。
それでスコア30000ぐらいとかだったしまだやれることもあったけどどんどん時間がなくなっていった。

結局nginx.confとmy.cnfをいじってる時間もなくてほぼデフォルトの状態のままだった。my.cnfは予め準備してたサンプルのmy.cnfからコピペしつつちょっと設定いじったりもしたけど特にスコアに反映されるようなことはできなかった。

最後masterも安定した状態になったよってことだったのでそれに変更してベンチマークとった。
最終的に送信したスコアは33000ぐらいだった。

あの無駄にした2時間あればもうちょいなんとかなったかもっていう悔しさばかりが残ってるけどこればかりは仕方がない。
我々西日本世界チャンピオンはチャンピオンになれなかった。

最後スコア33000↑で時間内に送信したはずやのにグラフには30000のが残ったままやなーそういうもんかなーって思ってたら、どうやら最後のベンチはreportのcheckのとこでfailしてたようでそれに気づいてなくてそのまま提出してしまってた。後日提出したAMIからインスタンスもっかい立ち上げてベンチマークとってみてその時気づいた。もう死ぬしかない。


今回の失敗によってISUCONを戦ううえで大事なことがわかった。
ご飯は食べよう。


本選に出場できないのはほんと悔しいけど初めてのISUCON予選すごく楽しかったので運営の皆様には感謝するばかりです。
本当にありがとうございました。

The scrypt algorithm

技術関連

scrypt(scriptではない)について調べた。何か間違ってたらご指摘下さい。

ググらビリティが最悪すぎて情報を探すのにすごく苦労した。。

Proof-of-work

BitcoinのProof-of-workではSHA-256が使われてるけど、LitecoinやMonacoinの場合はscryptっていうのが使われてるらしいってのを知って興味持ったので調べてみた。

scryptとは

Tarsnap - The scrypt key derivation function and encryption utility

  • ハッシュ方式の1つで、計算時に大量のmemoryを必要とするよう設計されている。
  • memoryを大量に必要とすることでブルートフォースアタックへの耐性を高めていると主張。
  • 一度の演算でmemoryリソースが大量に必要となればハードウェアにそれなりのスペックを要求することになる。
  • 昨今SHA-256の演算とかだと専用のチップとかですげー速さで演算できたりするらしいけどそういったことを困難にしている。

アルゴリズム

本家資料
http://www.tarsnap.com/scrypt/scrypt.pdf

簡易的な説明(図がわかりやすい)
http://alpha-t.net/wp-content/uploads/2013/11/Alpha-Technology-Scrypt-Analysis-on-FPGA-proof-of-concept.pdf

日本語での詳細な説明!!!(日本語での解説はこの方のblogしか見つけられなかった)
scryptを実装してみた 前編 | プログラマのつれづれなるままに

正味本家の資料見ただけじゃちんぷんかんぷんすぎて頭が痛くなった。。
頭の悪い俺にもわかりやすい資料を~~って探して図がわかりやすいのを見つけた。 なんとなく全体像がわかったけど詳細部分がいまいちまだ理解できなくて探してたら日本語で詳しく解説してるエントリ(最高!)を見つけて大体大雑把な感じで理解した。

細かい部分を理解するにはやっぱりコード見るのが早いなってことでscrypt実装のコード探してみた。

scrypt - Wikipedia, the free encyclopedia
ここに色んな言語での実装一覧があって、あっPerlもある~~~って思って見てみたけどXSで書かれてて全然読めなかった。つらい。
RubyとかPHPとかのコードもなんか .c ってファイルが見えたりしてアッアッてなって自分の無能さがただただつらかった。

で、ひと通り見て自分にとってはJavaの実装が一番わかりやすかった。
https://github.com/kocakosm/pitaya/blob/master/src/org/pitaya/security/SCrypt.java

ここまでの資料とか図とかコードとかを全部見てようやくなるほどーって感じになった。

キーとなっているのは BlockMix って書かれてるとこの処理で、ROMix の中で2回 BlockMix のフェーズがある。
どちらのフェーズでも1024回ループぶん回して(CPU/memoryのコストパラメータが 1024の場合) Salsa20(Rounds => 8) でハッシュ値をこねくりまわしてる。

最初のフェーズでは演算毎に得られたハッシュ値を全て保持するようにしている。ここがmemoryを一番使うところで、例えばブロックサイズのパラメータが 1 でCPU/memoryのコストパラメータが 1024 とかだと 128 * 1 * 1024 = 128kB のmemoryサイズを必要とする。
ブロックサイズのパラメータやCPU/memoryのコストパラメータを変更すると必要なmemory量も変化する。

2度目の BlockMix のフェーズでは上記で演算した結果を用いて1024回ループぶん回している。

memoryを必要としている仕組みがこれでわかったのでスッキリした。

スッキリしたついでに理解できてるかの確認も含めてXSじゃないPerl実装書いてみようかなと思ったけど、技術力もなけりゃ元気もないのでやめた。(`ェ´)ピャー

まとめ

たぶん2ヶ月もすれば全て忘れそう。