最高のインターネットと文脈の破片たち

この記事は KMC Advent Calendar 2019 - Adventar の13日目の記事です。

adventar.org

前日の記事は zeke さんの EDPC A~M問題についての備忘録 - Qiita でした。

ところでこの記事は怪文書の類の記事なので、 怪文書に慣れていない人は明日の Strelka さんの 闇鍋をした話 - strelka_dogのブログ を読みましょう!

はじめに

「最高のインターネットは文脈の破片たちから形成される」

これはとある人物のインターネット上での呟きです。 これについて述べることは無粋な行為なのですが、ここではあえてその禁忌を犯してみましょう。

みなさんは、インターネットに疲れていませんか。 「○○がxxしたから嫌だった」「○○がxxしてるwww」「xxするなんて信じられません!」「バカはすぐxxする」のような呟き・投稿、 こういう悪い感情の共有は巷に溢れていて、気を付けていないといつの間にか摂取してしまい、精神が徐々に疲弊していきます。

また逆に、「○○がxxだったから嬉しい!」「○○がxxしてくれた!」「xxするの最高!」「天才はxxしている」のように、良い感情の共有も溢れています。 これらは悪い感情よりは精神への影響は少ないのですが、これも他人への劣等感が少しずつ刺激され、精神を疲弊させる原因の一つとなります。

上記をまとめると、インターネットでの感情の共有が精神を疲弊させているのではないか、という考えが導かれます。 「最高のインターネットは文脈の破片たちから形成される」とはつまり、精神を疲弊させない「最高のインターネット」は、 感情を抜き取りただフォーマットに沿った事実だけが次々と投稿される「文脈の破片」から形成される、ということを述べているのだと私は解釈しました (この解釈は私個人によるものであり、当然「最高のインターネットは文脈の破片たちから形成される」と考えた人物の解釈とは異なる可能性が大いにありますので予め断っておきます)。

#kashi-tweet

ここからは文脈の破片たちから構成されるインターネットを紹介します。 #kashi-tweet は、KMCのSlackのチャンネルの一つで、その名の通り歌詞ツイ(歌詞の一部を投稿すること)だけが流れます。 このチャンネルは2016年11月5日に突如現れ、今日まで寂れることなく残っています。

gyazo.com

#go-go-575

#go-go-575 も、KMCのSlackのチャンネルの一つで、その名の通り575(≒川柳)だけが投稿されます。 このチャンネルは2015年3月3日に現れ、今日まで残っています。

gyazo.com

Nuita

部員が作成したNuita というSNSがあります。 このサービスの内容について言及するのは不適切な気がするので、以下の記事を読んでください。

kyp.hatenadiary.com

#飛ぶことは救いではない

文脈の破片を投稿するのが上手な人が居て、その人が文脈の破片を投稿するのでそれを愛であっていました。

gyazo.com

この文脈の破片は質が高く、昨年の夏コミで本にして出しました。 現在Boothで公開中です ( 飛ぶことは救いではない合同誌 - tobusuku - BOOTH )。

応用

折角なので現実のインターネットに応用してみましょう。 今回はTwitterを「漢字の破片だけが流れるSNS」に改造してみます。

5秒で思いつく以下のjsを実行します。

setInterval(()=> document.querySelectorAll("p.tweet-text").forEach(x=>x.innerText = (x.innerText.match(/[一-龠]/g) || []).join("")),1000)

gyazo.com

gyazo.com

精神に悪影響を及ぼしやすかったあのTwitterが、文脈の破片を紡ぐ最高のインターネットへと華麗に変身しました! やったね!

さいごに

明日の記事は Strelka さんの 闇鍋をした話 - strelka_dogのブログ です。たのしみ!

ポケモン剣盾でマスボ級にいったノーマル統一パの覚え書き

だいたい「エレザードホルードメタモン」の並びになりがち。

死ニーゴとかの面倒そうな相手が2体居るときにはタチフサグマが刺さるので入れる。 (死ニーゴはナイトヘッドやたたりめでしか攻撃できないことが多い(うずしおとかもあるのにね)ため殆ど選出されないので死ニーゴだけなら無視している)。

格闘対策は、イエッサン。 ルカリオローブシンが居ると大抵出してくれるのでイエッサンで叩く。壁ロンゲもだいたい悪を見てフェアリーわざしかないのでイエッサンのサイコメーカーで処理できる。 ルチャブルダイマックスイエッサンで倒すしか無いけど難しすぎるのでこれは出てきたら負けでいいです。

カビゴンは...環境外の強そうなやつがいるときに出すと壁になってくれるけどあんまり役に立ったことがないかも...バイウールーに変えようかな...

エレザードはとにかく強くて、バンドリをきあいだまで倒せる。 エレザード先手からのスカーフドリュのじしん連打の負け筋を引かなければだいたい勝てるのでカモ。バンギから入るとほぼ勝ち。 ダイマックスじゃくほで倒されてもホルードがいればばかぢからで処理できるし、ホルードが居ない場合は最大まで積ませてメタモンでパクって全抜きできる。 サザンドラアイアントを上から倒せるのもロトムには無い強み。 相手の知識がないとエレザードに水技を打ってくれることもあるし、そうでなくてもウォッシュロトムには対面勝ちできる。

スカーフホルードが結構強くて、スカーフ・タスキ・ハチマキ・ダイマックスのどのドラパルトでも対面イカサマで勝てるほか、ドリュも対面なら打ち勝てる。 ミミッキュもじしん連打でも倒せるし剣舞積み後ならイカサマでも倒せる。

メタモンが最強で、ダイマックスして強化したりじゃくほしてくれたらそれをまるまるパクってタスキか素早さ乱数勝利で打ち勝ったあと全抜きができるほか、 普通に状況に合わせて残りのメンバーでは処理しにくい相手を強引に処理できるので最強。 スカーフよりもタスキのほうが強い。スカーフだと(ほぼ)確定対面勝ちしか利点が無いが、タスキだと技が拘られないので状況に合わせて柔軟にへんしんできる。 先制技はあんまり見ないしミミッキュはかげうち合戦するだけだし積みエースに強すぎる。 メタモンにも弱点はあって、みがわり状態の相手にはへんしんができないのと、ばけのかわはコピーできない(相手のばけのかわが剥がれていなくてもこちらのばけのかわは剥がれてしまっている)のが痛い。みがわりとばけのかわは絶対に剥がすしかない。 ギルガルドのバトルスイッチもコピーできない(キングシールドを使っても変わってくれない)ので、なるべくブレードフォルムの方をへんしんできるようにしておきたい。 あとへんしんするとPP5になるのは弱みでもあり強みでもある。最後に害悪系が残ったときにへんしんするとPPで負けてわるあがきで死んでしまう。しかし仲間が居るとPP5にしてリセットができる。隙きを見て入れ替えれば無限のPPを得られるので1回勝てた。

よくある負け筋はエレザードとアーマーガー対面からのでんき技読みスカーフドリュ変えでじしん連打されること、これを読んでイェッサンが出せれば好転するけどむずい... 後はヌオー・トリトドン・ゴリランダー・オノノクス・(スカーフ)ヒヒダルマルチャブルはかなり相性が悪い. 上三体は読んでダイマックスイエッサンで処理するしかない。下三体は自身を強化してくれないし有効打も無いのでどうしようもない。出てきたら負けです。 カビゴンをこれらに有利なポケモンに変えたほうが良さそう。

あとメタモンで環境のパーティの技構成を完全に知れるため、こちらも今後それを対策できるのが一番偉かったかもしれない

ISUCON9本戦で10万点を取るにはひたすらハードコーディングとN+1をすればよい

ISUCON9本戦の感想戦をやっていきました。最終スコアは105417点です。

github.com

最終的な avaiabledays は100。DB1台,Webアプリ1台。

f:id:CHY72:20191029072331p:plain

過去のISUCONは傾向としてトランザクションが本質になりがちな傾向がありましたが、 今回のISUCONの本質はハードコーディングとN+1でした。

TLDR;

  • ひたすらハードコーディングとN+1消しをすれば点数がどんどん上がる。複雑なトランザクションも必要ない。
  • このブログにはN+1以外のことも書いてあるが、それはあんまりネックではない。本質はN+1。
  • ただひたすらにハードコーディング作業とN+1消去作業をしましょう。

やったことまとめ

10000点くらいまでの過程は省略。

N+1

  • 各席毎にDBに問い合わせるのをやめて、対象車の予約を一括で取ってきてアプリ側で席を管理することでN+1を消す。
  • getAvailableSeatsの対象となる列車リスト(およそ10車)を予め取得してから問い合わせることでN+1を消す。
  • あいまい検索で前から順に16車両分回すN+1も消す。
  • 他にも細々としたN+1を消す。

train_masterのハードコーディング

  • そのままでは流石にハードコーディングできないので、本質的なデータだけ(Departureの時分/{東京京都大阪名古屋}のペア(6通り),TrainClass)をハードコーディングする。

train_timetable_masterのメモ化

  • 数百万通りの可能性があるのでオンメモリにはできないが、実際にアクセスされるのはそれより遥かに少ないのでメモ化する。

キャンセル処理

  • bulkする。

ログイン・サインアップ・getUser

  • 本質ではない。下記をするとほのかにスコアがあがる。
  • Cookieのuser_idのデコードに時間がかかるので、同じユーザーのクッキーのデコードはキャッシュする。
  • Userデータを https://github.com/Muratam/go-syncmapserver で管理する。
  • SHA256のハッシュの回数を10回から1回に減らす。規定はないので。

ほか

  • あいまい検索時に二重にvalidationしているのをやめる。
  • インデックスは貼った方がお得なのでちゃんと貼る。

残りできること

  • getAvailableSeatsは理論的には消せるので消す。
  • そろそろ接続が増えすぎてコネクションが辛くなってくるのでDocker外しをしたりNginxやMySQLのそういうパラメータをチューニングする
  • 外部サービスへの接続のTLSハンドシェイクが下手くそなのでプーリングする。
  • reservations/ seat_reservations もhttps://github.com/Muratam/go-syncmapserver で管理する。
  • 複数台構成をする。
  • これは予想ですが多分上記をやってavaiabledaysを366にすると 200000点くらいは出ると思います。

やらなかったこと

  • 席予約アルゴリズムの変更。やる必要がなかった。
  • ベンチがHTTP2になってくれたらもっと点数出るのになー。

サイコロの旅のすすめ

TL;DR

18きっぷが余っていたのでサイコロを振って出た目が示す所を目的地とするのを繰り返すサイコロの旅をしました。

サイコロの旅

どこに行くのか決まっている旅もいいですけど、たまにはどこに行くのか分からない旅もいいと思いませんか? このサイコロの旅ではどこに行くのかはダイスを振って決めます。 予定が直前まで分からないので管理された旅が苦手な方におすすめです。

京都発

本家水曜どうでしょうに合わせて近く4駅,遠い2駅から目的地は万遍なく選びました。 柘植とかが出るとこのあとの発展性があるんですが、今回は関西空港になりました。

関西空港

次の目的地は和歌山になりました。

f:id:CHY72:20190914123010p:plain

関西空港に来ましたが、18きっぷを使うのが目的なので海外には行きませんし、当日飛行機は高価なので飛行機を使うわけでもありません。 その日はイベントもありません。 完全に「大阪から和歌山行きに乗ったが間違えて先頭車両に乗ってしまい関西空港に着いた人」です*1

周りが飛行機で旅たとうとしているなか、我々は改札で出した18きっぷで再度Uターンします。 まあこういう完全な無駄行動もサイコロの旅の醍醐味ですね。

ちなみにサイコロの出目によっては,関西空港から神戸港のフェリーに乗ったり、すきっぷ2000というお得きっぷを使うレアな機会があったのですが、これらの目は出ませんでした、悲しい〜

和歌山

f:id:CHY72:20190914123544p:plain

徳島が出ました!フェリーか〜〜〜〜〜〜〜〜!

和歌山城・和歌山ラーメンを観光。

知っている人は知っている、和歌山の地酒高垣を売っている酒店です。

www.sankei.com

デレの不思議な縁でできた観光地になっており、前に来たときよりも随分とグッズが増えていました。 こういうところはいいですね。

フェリーに乗るとやたらとこのアニメがプッシュされていました。 「おへんろ。」という四国ローカルアニメらしいです。

どパスコが可愛かったのでツボに入りました。

徳島

f:id:CHY72:20190914123827p:plain

というわけで最終目的地は小歩危(大歩危)になりました。 歩くのが危険と書いていますが、それは昔の話で今は道も整備され電灯もあり、歩くのは容易いです。

2日目

2日目もサイコロを振ると帰れなくなるので普通に大歩危を観光して帰ります。

さいごに

サイコロを振って結果が出るまでどうなるか全然わからないのはかなり楽しいので、旅にちょっとしたスパイスをかけたいかたはぜひサイコロの旅をおすすめします。

おわり

*1:この列車は先頭4車両は関西空港に、残りは和歌山に行くことが多い

nim-lang/Nim に issue を建ててちょっと恥ずかしい思いをした話

TL;DR

  • Nim で C++ の std::set のラッパーを書いた
  • 奇妙なコンパイラのバグを踏んだのでNimにissueを建てた
  • 4年前に建てられていたissue と同様のものだったために close された、恥ずかし〜

はじめに

私は Nim が好きでNimをよく書いています。 最近AtCoderでstd::setを使う問題がよく出題されており、 Nimでも C++ の std::set を使えるようにラッパーを作っていました。

github.com

ところが、これを使用した方からコンパイルエラーが出るという報告をいただきました。

コンパイルエラー

type CSet {.importcpp: "std::set", header: "<set>".} [T] = object
proc cInitSet(T: typedesc): CSet[T] {.importcpp: "std::set<'*1>()", nodecl.}
proc insert[T](self: var CSet[T],x:T) {.importcpp: "#.insert(@)", nodecl.}
proc `==`[T](x,y:CSet[T]):bool{.importcpp: "#==#", nodecl.}
var (S1,S2) = (cInitSet(int),cInitSet(int))
S1.insert 1
if S1 == S2: echo "wrong"
else: echo "correct"

このコードをコンパイルすると、以下のエラーがでて、NimからC++に変換した後のC++コンパイルに失敗します。

Error: execution of an external compiler program 'clang++ -c  -w  -~/.choosenim/toolchains/nim-0.20.0/lib -I~/codes/nim/ -o ~/.cache/nim/t_d/t.nim.cpp.o ~/.cache/nim/t_d/t.nim.cpp' failed with exit code: 1

~/.cache/nim/t_d/t.nim.cpp:153:7: error: invalid argument type 'TY_89ajMAHL4D29bP2aGRstu1mQ' (aka 'set<long long>') to unary expression
                if (!S1_X5vbOHyI0SI13LVkxEIzEQ==S2_q2YrwwKwgOf4xdemDnRTYA) goto LA4_;
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

ほう、という感じですね、

このC++コードの全文は以下です。

N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
    tyTuple_WVskh7WUQHL0ugdByxngAw T1_;
    nimfr_("t", "/path/to/t.nim");
    nimln_(8, "/path/to/t.nim"); 
    T1_.Field0 = std::set<NI>();
    T1_.Field1 = std::set<NI>();
    S1_X5vbOHyI0SI13LVkxEIzEQ = T1_.Field0;
    S2_q2YrwwKwgOf4xdemDnRTYA = T1_.Field1;
    nimln_(9, "/path/to/t.nim"); 
    S1_X5vbOHyI0SI13LVkxEIzEQ.insert(((NI) 1));
    nimln_(10, "/path/to/t.nim"); 
    {
        if (!S1_X5vbOHyI0SI13LVkxEIzEQ==S2_q2YrwwKwgOf4xdemDnRTYA) goto LA4_;
{       echoBinSafe(TM_earX20ePV9cxitomwdUMS7g_2, 1);
}   }
    goto LA2_;
    LA4_: ;
    {
        nimln_(11, "/path/to/t.nim"); 
        echoBinSafe(TM_earX20ePV9cxitomwdUMS7g_4, 1);
    }
    LA2_: ;
    popFrame();
}
}

このエラーを見ると分かるように、要は if S1 == S2: ... の条件分岐を C++ に翻訳した時に、 if (!S1 == S2 ) goto LA4_; になってしまっているようです。 条件分岐をミスっている様子で、これは正解は if (!(S1 == S2 )) goto LA4_; となるべきですね。

つまり、if A == B: X else: YC++に翻訳する際に、 if (!(A == B))Y; else X; となるべきところを、 if (!A == B)Y; else X; としてしまっているわけです。どうして否定が入っているのかはわかりませんが、条件分岐のときにだけコンパイルが失敗するので、最適化か何かの都合で混入したバグなのでしょう。

nim-lang/Nim に issue を建てる

このバグは最新のNim0.20 でも発生します。流石にこれを放っておくわけにもいかないので issue を建ててみます。 勿論、(これはOSSを使うときには今までもよくあることなのですが) すでに issue で議論されていないか確認すべきです。 今回のissueに関連するワード equal function if override の単語で検索し、既に議論されていないか確認します。 無さそうだったので、早速 issue を建てます。

f:id:CHY72:20190913191300p:plain

こんな感じで、Bug Report のissueを建てようとすると、指針としてテンプレートが既に書かれています。便利ですね。 これに従って書いていけばよさそうです。

Think about the title, twice

と初めに書いてあります。タイトルは大事ですからね。 普段技術文書を英語で読むことはよくあるのですが、それに対して英語を書くのはとても苦手なので最低限文法が間違っていないかをgrammarly でチェックします。

そしてこれは戒めなのですが、最低限文法が通っているにしても意味が最低限間違っていないかをチェックするために Google 翻訳に2回かけるやつもやっておくべきでした...(英語→日本語→英語 or 日本語→英語→日本語 をして意味が崩れないかチェックするやつ)

例えば 建てた issue の冒頭、

Overriding equal function causes incorrect behaviour. Nim compiler translates !(a == b) into !a == b and fails to compile.

と拙い英語で書いていたのも、

Overriding an equal function will cause incorrect behavior. Nim compiler converts !(a == b)! to a == b and fails to compile.

になって、なんとなくこっちのほうがいい感じな気がします(非ネイティブ並の感想...)*1

なんやかんやあって issue を建てました。 github.com

回答が来る

f:id:CHY72:20190913192953p:plain

要は # == # (#は出てきた順にその番目の引数を表す) ではなくて、 (# == #) と定義してくれとのこと。なるほど *2Low Priority のタグが付きます。

実は duplicate issue だった

f:id:CHY72:20190913193456p:plain

その後、これは duplicate issue だよ、と指摘されます。あちゃ〜やっちまった〜〜。 そういうわけで4年前に建てられたissueと同一の内容であったので close されました。 Low Priority なので 4年間放置されていたバグであっても仕方がないですね。

恥ずかし〜〜〜〜〜〜〜〜〜〜

どうすれば duplicate issue を回避できたか、 equal function if override で検索したのに加えて C++ compile error でも検索する、もしくは Label:C++ codegen を探しておく、が正解だったっぽいですね。

う〜 。

未来永劫 duplicate issue を建てた者としてnim-lang/Nimに記録が残るのはちょっと悲しいですね〜〜〜。

総計 12028 件の Nimのissueのうち duplicate を含む issue は たった 502 件 しかなくてそのうちの一つになっちゃったな〜〜〜〜。

うひ〜〜〜。

あ〜〜〜〜〜〜〜〜。

おわり。

*1:というか function って可算名詞ですね。

*2: ちなみに、Nimの流儀として全ての二項演算をこのように (#+# ではなく (#+#) と書く) 定義するといった指針はありませんのでこれは特殊な書き方と言えます。

パスワード を 平文 で保存していませんか???パスワードの最強の保存方法「Piet埋め込み」について調べてみました!

こんにちはwwwwww!!!!

暑い日が続きますねwwwwwww!

突然ですが、あなたはパスワードをどうやって保存していますか???

平文のままテキストファイルに保存していますか?

それとも適当なハッシュ関数でハッシュ化してそのハッシュをテキストファイルに保存したりしていませんか???

実はそれ、 とっても危険な保存方法 なんです!!!!!!!!

テキストファイルに怪しい文字が書いてあった場合、どんなに強いハッシュ関数でも賢い人達が衝突させてしまう可能性があります!!!!!!!!

大変ですよね!!!

一体どうすればいいんでしょう?????????

Piet

テキストファイルに怪しい文字を保存するのは危険 ですよね!!!!

なので、実はパスワードは画像に埋め込むべきなんです!!!!!!!!!!!

ここではオススメの埋め込み方法として、Piet にパスワードを埋め込む方法 を解説します!!!!!!!

f:id:CHY72:20190911175649p:plain

(元画像は 東方32×32打ち直しシリーズまとめ! - えるるのだいあり ~Season2~ よりお借りしています!!! )

この画像は何の変哲もない32x32のフランちゃんのドット絵ですよね!!!!!!!!!

でも、この画像はなんとPiet として実行できる んです!!!!!!!!!!

実際にこの画像を(npietなどで)実行すると 「PietPiet」と表示されるんです!!!!!!!!!!

この「Piet埋め込み」 の方法を使えば安全にパスワードを保存できますね!!!!!!!

さらにさらに、僕は頑張ったので 好きな文字を好きなドット絵に、なるべく原型を保ったまま最良優先探索をしてPietとして埋め込むプログラムが既に存在してるんです!!!!!!!

f:id:CHY72:20190911180316p:plain

すぐに使える実装コードはこちら!

github.com

この「Piet埋め込み」 の方法を使えば安全にパスワードを保存できますね!!!!!!!

さいごに

いかがでしたか??

もしパスワードを平文やテキストのまま保存していた場合はこの記事のようにパスワードをPiet化して保存したほうがいいかもしれませんね!

この記事が役に立ったら欲しい物リストのものを買って下さい!

https://amzn.asia/4n4xnzC

ISUCON9で予選通過したのでbcryptについて書く

はじめに

ISUCON9の本戦出場が決まりました. 今年から学生枠が無くなったためかなり厳しい状況になるな〜と思っていましたが、チームメンバーのおかげで通過できました.

リポジトリはこちら

私のチーム(百万円ドブリン)の状況は@nakario のブログ に詳しく書いてあるのでそちらをご参照ください. 私がしたことはbcryptをいじっていただけだったのでチームメンバーの力が如何に素晴らしいかがわかります。

bcrypt 改善について

実は去年の本戦でもbcryptが出題されていました。 GoアプリのCPUフレームグラフを見るとbcryptの処理が支配的になるのですが、 その時はGoアプリのCPUはネックになっていないため、そこをどんなに改善してもスコアが上がらない、という構成でした。 昨年はここを改善しようとして沼にハマって大敗しました。 詳しくは isucon8本戦は低レイヤーがネックにならない良問だった - (/^^)/⌒●~*$ a(){ a|a& };a を読んでいただければ。

うって変わって今年の bcrypt はかなり強めの主張をしてきました。 アプリをチューニングしていくと頻繁に login 処理が入るようになり、bcryptの処理が支配的かつCPUを大量に消費するようになります。

f:id:CHY72:20190911145737p:plain

これの直し方は以下の2つがあります。

  1. こちらが持っているハッシュ化済みのパスワードからもとのパスワードは推測できないので、ベンチマーカーからのログインを盗聴してハッシュアルゴリズムを変更し、徐々にコスト10のbcryptを取り除いていく。
  2. 本質的に改善不可能な処理なので、ログイン専用サーバーを構築し、処理を分散させる。

私は最初は1の方法を取ったのですが、実はログインはそんなに成功しないことが分かりました。 そのため試算の結果では数十回ベンチを回す必要がありそうでした*1。 加えてこの盗聴作業は楽しくなかったため、我々のチームはログイン専用サーバーを構築することにしました。 Nginxでどうやるんだったけ...とぼーっとしていたら aokabi がシュッと実装してくれました。

f:id:CHY72:20190911151158p:plain

17時前、複数台にした途端点数が跳ね上がりました。やったぜ。aokabi最高! 勝利! もちろんbcryptが支配的になるまでチューニングしてくれたnakarioも最高! 優勝!

Go の bcrypt は遅い?

本戦終了後、twitterを見ていると 「Goのbcryptは遅い」という主張がたまに目につくようになります。 これは例えばPythonのbcryptは(Pythonそのままでbcryptすると遅すぎるので)内部的にC言語で書かれており、 そのためGoのbcryptとくらべて速いのでは、という主張です。 一理あったのでGo/Python/Rubyの3バージョンで雑に計測してみます*2

コードはこちら

結果、Go実装は15秒,Python実装は14秒,Ruby実装は13秒でした。Go実装はちょっとだけ遅いものの、そこまで差は無いように見えます*3*4。 どの言語を選んでもbcryptと向き合う必要がありそうです。

最後に

感想戦をする時に盗聴をしなくてもbcryptを完全に排除できるように、 全ユーザーの生パスワードを抽出したjsonファイルを作りました!お使い下さい!

今回こそは100万円を取るぞ!

*1:bcryptをほぼ完全に取り除く場合,実際はもっと少なくても効果はでうる

*2:@手元のMac(core i5 / RAM8GB)でgo 1.11.5 / python3.7.4 / ruby 2.3.7

*3:PythonについてはCの最適化がなされていない可能性を考慮し、手動でCソースをO2/O3をつけてビルドしたPython非経由の実装も試してみましたが結果は同じでした

*4:もちろん、環境によっては特別な最適化がなされて速度が変わる可能性はあります