うなすけとあれこれ

2017年10月22日

ISUCON 7 やまのほすけ 提出スコア 11,204

落ち着くこと

メンバー

やったこと(順不同)

僕らが高速化したのはRuby実装です。

MySQLのチューニング by のほ

まずはslow query logの有効化、それからinnodb_buffer_pool_sizeを1Gにしました。

deploy scriptの作成 by うなすけ

今回はサーバーが複数台あるので、手元で叩いて各サーバーにssh経由でgit pullsudo systemctl restartをさせようと思ったのですがなかなかうまくいかず、結局サーバーにsshした上で実行するscriptになってしまいました。

このscriptはちょこちょこ書き替えが発生していました。

user.nameにindexを張る by うなすけ

CREATE TABLE user (
  id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  name VARCHAR(191) UNIQUE,
  salt VARCHAR(20),
  password VARCHAR(40),
  display_name TEXT,
  avatar_icon TEXT,
  created_at DATETIME NOT NULL,
  INDEX(name)
) Engine=InnoDB DEFAULT CHARSET=utf8mb4;

ただ、このQueryを実際に流すのを忘れていて、終了10分前とかに気づいてIndexを張ったというポカミスがあります。

RACK_ENVをdeploymentに by うなすけ

定石というか、なんというか。あわせてAPP_ENV(Sinatra)もproductionにしています。

静的ファイルをnginxから返すように by やまま

これも定石。しかし、nginxから返すようにしてから数十件の静的ファイルへのリクエストがタイムアウトするようになってしまいました。はじめはnginxが詰まったのだろうか……と考えていましたが、その後Discordでeth0で頻繁にネットワーク遅延が発生していると報告がなされました。もしやと思って僕からnginxへのリクエストがタイムアウトする旨を使えたところ、報告された方も同様の症状だったそうで、「これはインスタンスガチャか……?」となりました。

しかし競技終了後、Cache-control publiclast-modifiedEtagの値などは考慮していないことに気付き、やはり自分達に原因があったのでは……となりました。(このへん詳細ちょっと不明です)

/loginと/registerへのGETを静的に返す by うなすけ

これは最初、アプリのコードを読むと静的やんけ〜〜となったので雑にpublic以下にhtmlを生成して置いたところ、ステータスコードでひっかかってダメでした。nginxで返すときにステータスコードも強制的に302に書き替えたりもしてみましたが、Locationヘッダーも必要でアーそうですねとなって一旦撤退しました。

しかしその後、「一度File.openとかで変数に格納して、それを返すようにすればいいのでは?」と気付きを得てそのようにしたところ、有意なスコアの上昇が見られてよかったです。もっと早く気付くべきですね。

N+1となるクエリをjoinで解消 by うなすけ

/message/history/:channel_idへのGETは、その内部で実行しているSQLにN+1問題があることがわかります。なので、これをjoinして解決することにしました。

 statement = db.prepare(
   'SELECT message.id, message.created_at, message.content, message.user_id, user.name as user_name, user.display_name as display_name, user.avatar_icon as avatar_icon FROM message INNER JOIN user ON user.id = message.user_id WHERE message.channel_id = ? ORDER BY message.id DESC LIMIT ? OFFSET ?'
 )
 rows = statement.execute(@channel_id, n, (@page - 1) * n).to_a
 statement.close
 @messages = []
 rows.each do |row|
   r = {}
   r['id'] = row['id']
   statement = db.prepare('SELECT name, display_name, avatar_icon FROM user WHERE id = ?')
   r['user'] = statement.execute(row['user_id']).first
   r['user'] = { display_name: row['display_name'], avatar_icon: row['avatar_icon'], name: row['user_name'] }
   r['date'] = row['created_at'].strftime("%Y/%m/%d %H:%M:%S")
   r['content'] = row['content']
   @messages << r
 end

hashにぶち込んでレスポンスを返すところ、特にuserの情報の部分では、/history/:channel_idではerbから参照しているのでhashのkeyがSymbolになっているとベンチマークでエラーが出るのにはちょっとハマりました。

あと競技終了後のDiscordで、statement.closeの漏れがけっこうあることを指摘されていて、この辺の知識がなくstatement.closeの有無がどう影響してくるのか不明で放置してしまっていました。

/fetchでのsleepを5秒にした(けどやめた) by うなすけ

レギュレーションには/fetchへのアクセスは採点対象ではないことが書いてあり、/fetchへのアクセス回数を減らせられればその分リクエストの処理が可能なのではないかと思い5秒までのばしてみましたが、ベンチで有意なスコア上昇が見られなかったことと、pumaのスレッド使い尽したらリクエスト受けられないのでは?と思いrevertしました。短くしようかとも思いましたが時間が足りず挑戦していません。

Varnishを用いたリクエストの分散 by やまま

もともとサーバーそのものは3台提供されていましたが、リクエストはapp1台とdb1台で処理していました。

これをVarnishにより、まずリクエストはapp1で受け、/profileへのPOSTと静的ファイルへのリクエストはapp2のnginx + pumaで、それ以外はapp1のpumaで受け、裏のdb1にデータを取りに行くという構成にしました。

多分今回のなかで一番大仕事かつ成果のあった作業だと思います。(これでベストスコアが出た)

よくわからなかったところ

pumaが重くなっていく

長時間サーバーを起動しっぱなしにしていると、/initializeが規定時間内に終わらなくなってしまいました。これは、isubata.ruby.serviceの再起動で解消されるので、ベンチマーク実行前にserviceの再起動をかけるようにして凌いでました。

感想

去年の提出スコアが0だったことを考えると、スコアが11204というのはもう去年の何倍というスケールには収まらない成長っぷり(?)でめちゃくちゃ嬉しいです。が、もっとやれることあっただろ、というところでもあります。

あと予習とか訓練が足りなかったかなーと思います。(2週間前にisucon4の予選問題でリハーサルをしただけ)

行動ログ

分単位で記入していますが曖昧です。

時刻 行動
9:05 うなすけ 会場準備
11:41 うなすけ ラブライブ サンシャイン 1期完走
13:00 競技開始、みんなで予選当日マニュアルのgistを読む
13:10 うなすけ Ruby実装を使うようsystemctlで設定、初期実装でのスコアを見るため先頭2台をenqueue (6173)
13:19 うなすけ アプリのコードをローカルにscp
13:24 うなすけ private git repositoryを用意
13:30 以降 うなすけ → deploy script、のほ → MySQL、やまま → アプリ理解 に分担
14:32 のほ slowquerylog など有効化
14:34 うなすけ deploy scriptの大枠が完成
15:00 ごろ やまま インスタンス内からbundler消失疑惑がありあたふた
15:26 やまま systemdの設定とnginxの設定をrepository管理下に
15:37 うなすけ RACK_ENVをdeploymentに
15:43 のほ innodbbufferpool_sizeを1GBに
15:45 うなすけ user.nameにINDEXを張る(コード上のみで実際には張らず)
15:48:40 スコア 6227を記録
16:03 うなすけ SQLのJoin化に着手
16:07:40 スコア 6403を記録
17:00 ごろ やまま 静的ファイルをnginxから配信するように悪戦苦闘中
17:23 うなすけ SQLをJoinするように
17:44:30 スコア 5698を記録
17:45 やまま pumaとnginxの間をunix domain socketで繋ぐ
17:46:46 スコア 8540を記録
18:08 うなすけ /login と /registerのGETをnginxから返すようにする
18:48 うなすけ /login と /registerのGETをnginxから返すようにするのをやめる
18:54:47 スコア 10852を記録
18:56:27 スコア 8248を記録
18:57 やまま Varnishの導入に着手
18:59:24 スコア 3016を記録
19:04:44 /initializeがTimeoutし始める
19:17 うなすけ /fetchで5秒sleepするようにしてみる
19:27:48 スコア 5678を記録
19:39 やまま Varnishを使ったrequestの分散に着手
19:51:22 スコア 4032を記録
19:57 うなすけ /fetchで5秒sleepするコードをrevert
20:00 やまま Varnishを使ったrequestの分散を完了
20:00ごろ みんなで他になにかできるか確認
20:31 うなすけ /loginと/registerを変数から返すようにする
20:31:26 スコア 11246を記録
20:35ごろ あまり覚えてないけど再起動試験とかしてたはず
20:40 user.nameにINDEXが張られる
20:42:42 スコア 12033を記録(ベストスコア)
20:51:28 スコア 11204を記録(提出スコア)

追記

2017-10-23 0:14

誤字の修正とメンバー紹介を追加しました。 (ykztsさんありがとうございます 🙏 )

2017年10月22日
2017年10月21日

高専DJ部 #15 でした

kosendj-bu #14

セトリ

  1. aaaa
  2. Fight My Way feat. Moses Keenan (Extended Mix) - Morgan Page, Moses Keenan
  3. With You feat. Emelie Cyreus (Progressive Extended Mix) - Magnificence, Venomenal, Emelie Cyreus
  4. Forever (Kill The Buzz Extended Mix) - Rico & Miella
  5. Party Till The Daylight feat. D3FAI (D3FAI Remix) - Hardwell, D3FAI
  6. Do Or Die feat. Lara (Extended Mix) - Lara, Blasterjaxx
  7. What It Looks Like (Extended Mix) - Daniel Garrick, Karra
  8. Rumble (Extended Mix) - Reggio, Sansixto
  9. What It Looks Like (Extended Mix) - Daniel Garrick, Karra
    • ミスって同じ曲を2回流すという失態
  10. Rage (Extended Mix) - Arston
  11. Kreatine (Original Mix) - Adam Sky
  12. Whatcha Need (Extended Mix) - W&W
  13. Break The House Down (Hardwell Extended Edit) - Kill The Buzz

aaaについて

このイベントで新曲披露できなかったら土下座と宣言して、なんとか土下座せずに済みました。タイトルは色々な音を弄ってみるために適当に付けたプロジェクトファイル名がそのまま残っています。

欲を言えば高専DJ部の度に1曲つくっていきたいけど、できるかな……

評判

スノーで加工されてリアルタイムでVJのおもちゃになってるうなすけ君の様子です #kosendj pic.twitter.com/hozPlyaKed

— とーかさん🦐10/21 kosendj (@touka_tt) 2017年10月21日

うなすけくん、DJだけはどんどんチャラくなっていく #kosendj

— HolyGrail@10/29ハコクラ (@HolyGrail) 2017年10月21日

うなすけくんこのままナイトプールDJとかやったら虚無捨て太郎いけそう(いや、いけない) #kosendj

— HolyGrail@10/29ハコクラ (@HolyGrail) 2017年10月21日

DJ. DJだけチャラ太郎 じゃん #kosendj

— JC手作り料理@10.21(土)茶箱 (@furaji) 2017年10月21日

スピーカーからモテたいという気持ちが伝わってくる #kosendj

— あそなす@高専DJ部10/21早稲田 (@asonas) 2017年10月21日

VJのお気持ちが出てしまった #kosendj pic.twitter.com/H41DB1MuM0

— HolyGrail@10/29ハコクラ (@HolyGrail) 2017年10月21日

これからもチャラチャラズンズンパリピEDMでやっていくぞ!!!!!!!!

2017年10月21日
2017年09月24日

FINAL FANTASY XIVを始めました

FF14 complete pack

経緯

経緯です pic.twitter.com/pvO2zH6ODy

— 🌈✨HolyGrail✨🌈 (@HolyGrail) 2017年9月7日

うなすけくんにFF14のゲームカードをプレゼントします! #光のうなすけくん https://t.co/2r1biLIlF7

— 🌈✨HolyGrail✨🌈 (@HolyGrail) 2017年9月18日

プレゼント完了しました!!! #光のうなすけくん pic.twitter.com/5vRGzoHo9u

— 🌈✨HolyGrail✨🌈 (@HolyGrail) 2017年9月18日

#光のうなすけくん pic.twitter.com/p6hUAgyhzG

— うなすけ (@yu_suke1994) 2017年9月23日

詳しくは #光のうなすけくん でよろしくお願いします。

#光のうなすけくん - Twitter検索

いやー、おとなってこわいですね!!!!!

これから

敵に絡まれまくるUnasukeちゃんが可愛い。 #光のうなすけくん pic.twitter.com/Uc5uiSbZ9d

— ふーすのー (@fooyuta) 2017年9月23日

ふーすのーありがとう……

とりあえず200日くらいは遊べる(ありがとうございます)のでやります。気が向くか要求されたらYoutube Liveで配信もします。以後よろしくお願いします……

2017年09月24日
2017年08月31日

高専DJ部 #14 でした

kosendj-bu #14

セトリ

  1. Ritual (Extended Mix) 催眠Mix - Sunstars
  2. Sushi Of God (Original Mix) - Nom De Strip, Nezzo
  3. Showdown (Extended Mix) - Maddix, LoaX
  4. Show Me Your Love (Extended Mix) - Firebeatz, Lucas & Steve
  5. Booyah feat. We Are Loud & Sonny Wilson (Original Mix) - Showtek, Sonny Wilson, We Are Loud
  6. 薬物はやめろ - SHO
  7. Freak It (Original Mix) with 黒柳徹子 - Dual Size
  8. Saving Light (NWYR Remix) [feat. HALIENE] - Gareth Emery & Standerwick
  9. Time To Jack (Extended Mix) - TJR
  10. アンパンマンたいそう with キズナアイ - ドリーミング

録音で片方のチャンネルがごっそり抜け落ちているので聞いてると違和感があるかと思います。

感想

今回は色々がありましたね…… そうめんが美味しかったです。

抱負

さて、

の3曲は、FL Studioを買って編集したものなのですが、打ち上げで「曲作らないの」と言われたので、次回の高専DJ部までに1曲作ることを目標にします。

togetter

KosenDJ-bu #14 - Togetterまとめ

2017年08月31日
2017年08月14日

Hyper.shでTwitter botを運用する

hyper.shのコンソール

Hyper.shとは

Hyper.sh - Container-native Cloud

Hyper.shは、とても手軽にDocker containerをhostingできるサービスです。課金は秒単位で行なわれ、一番安いプランだと月に$1ちょっとしか費用がかかりません。

これを使って、特定の単語に反応するTwitter Botを運用してみます。

Twitter Botを作る

Applicationの作成

Twitter Application Management

まずはここからCreate New Appします。Consumer KeyConsumer SecretAccess TokenAccess Token Secretを入手します。

Bot本体の作成

今回つくるBotは、特定の文字列からなるDMを受けとったときに返信するというものです。

require 'logger'
require 'twitter'
logger = Logger.new(STDOUT)

config = {
  consumer_key:        ENV['CONSUMER_KEY'],
  consumer_secret:     ENV['CONSUMER_SECRET'],
  access_token:        ENV['ACCESS_TOKEN'],
  access_token_secret: ENV['ACCESS_TOKEN_SECRET'],
}

rest_client = Twitter::REST::Client.new(config)
logger.info 'REST client initialized'

streaming_client = Twitter::Streaming::Client.new(config)
logger.info 'Streaming client initialized'

streaming_client.user do |tweet|
  if tweet.is_a?(Twitter::DirectMessage) && %r[\A年収\z].match?(tweet.text)
    logger.info "Recieved DM #{tweet.text} from #{tweet.sender.screen_name}"
    rest_client.create_direct_message(tweet.sender, "#{ENV['ANNUAL_INCOME']}万円")
  end
end

このようになりました。

unasuke/annual-income-bot

Hyper.shにdeployする

さて、まずはこのDocker imageをDocker Hubにpushします。 unasuke/annual-income - Docker Hub

次に、hyperの中にpullしてきます。hyperをローカルマシンと同様のものだと考えるとわかりやすいかもしれません。

$ hyper pull unasuke/annual-income:v0.1.1

そして、docker-compose.ymlを作成してあるので、次のコマンドでもうBotが動作し始めます。

# project名にハイフンが使えないと怒られたので直接指定
$ hyper compose up -d -p unasuke_annual_income

という訳で、僕に「年収」とだけ書いたDMを送ると僕の年収が返ってきます。

超簡単Hyper.sh

どうですか、Hyper.sh。ちなみにプランは自動で決まるのか、僕のBotはS4(月$5.18)で実行されています。

以下にinvitation linkを置いておくので是非活用してください。 https://console.hyper.sh/register/invite/yApE4Arn3osDm9RPDG3LuLJPj1BwR8fK

訂正(2017/08/15 00:27)

デフォルトでS4になり、docker-compose.yml内で指定できるそうです。

Compose File Reference | Hyper.sh User Guide

2017年08月14日
2017年07月15日

Oculus Riftを買った

oculus rift

サマーセールだったものでつい

もともと去年組んだPCは、VRを楽しむために組んだものでした。でも資産的に厳しい状態が結構続き、VRデバイスには手を出せずにいました。

そしたらなんと、Oculus Riftがいきなり5万円まで値下げしたじゃないですか。数十分悩んだ末、購入を決めました。

というわけで、やっていきましょう pic.twitter.com/PZVuuv5Xmk

— うなすけ (@yu_suke1994) 2017年7月15日

装着感

僕は眼鏡をかけているのですが、Oculusを装着するのが一番大変で、コンテンツの視聴やゲームのプレイ自体には支障ありませんでした。

しばらくしたら少し小さめの眼鏡を買おうと思います。

操作感

セットアップの過程でセンサーによる部屋の認識が(と言っていいのか?)あるのですが、それにてこずりました。そんなに広くない部屋なので、何度も「もう少し離れてください」と表示されてしまいました。

ゲーム

サマーセールで購入した場合には、5つほどのゲームが無料でバンドルされてきます。そのうちで惹かれたRobo Recallをやってみました。

Robo Recallが、というよりやっぱりVRはすごいもので、VRという意識が薄れていないゲーム開始時のムービーですらヒヤッと思わせられました。没入感がとにかく凄いです。

操作性に関しては、僕があまりゲームをやらないのと、とにかく敵が迫って来て焦るので、終始わちゃわちゃしてしまいました。

総評

ヤバい

2017年07月15日
2017年06月18日

maekawaのversion 0.5をリリースしました

清楚前川

Released! 🎉

上のみくにゃんはリリース記念に描きました。やる気の続く限り、maekawaのリリースごとにみくにゃんを描いていこうかと思います。

「前川みく」/「うなすけ」のイラスト [pixiv]

What’s new?

TargetのRoleArn指定対応

いつの日からか、TargetにもIAM Roleを指定できるようになっていたのでそれの対応をしました。

Profile指定対応

cliで実行するときに、aws credentialのprofileを指定して実行できるようにしました。

EcsParameters対応

今回のリリースのメインです。

Amazon ECS Now Supports Time and Event-Based Task Scheduling

spice lifeでは CloudWatch Eventsからecs taskを実行するのに、今まではlambdaを中間層として実行していました。

しかしTime and Event-Based Task Schedulingによって、中間層となるlambda functionが不要となり、直接ecs taskを実行できるようになりました。

今回のリリースで、maekawaからEcsParametersを取り扱えるようになりました。

KinesisParameters対応

いつの日からか、Kinesisにも対応していたのでmaekawaでも取り扱えるよう対応しました。

しなかった対応

InputTransformerとRunCommandPrametersには対応していませんし、今後するつもりもありません。

理由として、まずこの2つの機能をspice lifeで使っていないこと、そして実装が困難であることが理由です。

Golangを初めて触って作成した初めてのcli applicationなので、実装にまだ整理されていない部分があります。その上、言語知識がまだ不足しているので、複雑な構造の型への対応が今の僕には困難です。

なので実装予定はありません。

ただ、もちろんPullRequestを頂けるのならありがたく頂戴しますし、Amazon Wishlistなどの手段で圧を掛けてくだされば実装する気持ちになると思います。

今後の予定

outputをもうちょっとかっこよく(色とか差分とか)できたら1.0.0としてリリースしたいですが、いつになるかは未定です。

2017年06月18日
2017年05月22日

middleman-hatenastarというgemをつくりました

howto page

つくりました 🌟 🌟 🌟

@yu_suke1994 あなたとはてなスター、いますぐ設置 https://t.co/sihB5jvGDx

— あそなす (@asonas) 2017年5月17日

ということがあり、つくりました。

Tokyo Middleman Meetup#3 - connpass というイベントを開催したのですが、そこでのLTでlive cordingをして、日曜から清書してできあがり、という経緯があったりします。

つかいかた

はてなスターのトークンを取得する

はてなスターをブログに設置するには - はてなスター日記

を参考に、トークンを取得してください。

middlemanの設定でhatenastarを有効にする

これは例です。詳しくは はてなスターをブログに貼り付ける - はてなスター日記 を読んでください。

activate :hatenastar,
  token: 'your token',
  uri: 'h2 a',
  title: 'h2 a',
  container: 'h2',
  entry_node: 'section.article'

layoutにhatenastar_tagを設置する

<head>のどこかで = hatenastar_tag を呼び出して完了です。

また、引数でconfig.rbの設定値を上書くこともできます。

= hatenastar_tag(entry_node: 'div.article')

既知の問題点

複数要素に対応していない

エントリの複数指定、1エントリ内での複数スター表示にまだ対応できていません。pull requestを送ってくれてもいいんですよ ❓

よろしくお願いします

とりあえずスター連打してください。

2017年05月22日
2017年05月17日

middleman-somemojiというgemをつくりました

somemoji

つくりました :v: :v: :v: :v:

middlemanでemoji記法 :example: をemoji画像に置換するmiddleman pluginをつくりました。 🎉

unasuke/middleman-somemoji

あ、middleman v4以降必須です。

動機

絵文字使いたかった、けどunicode emojiの入力ってけっこうしんどい、なのでGitHub風に絵文字を入力したかった。

できるならemojiのproviderも選べるようにしたかった…… そんな感じです。

つかいかた

bundle install

Gemfileに次の行を追加して、bundle installします。

gem 'middleman-somemoji'

somemojiを使ってemoji画像をひっぱってくる

$ bundle exec somemoji extract --provider=twemoji --destination=./source/images/emoji

このへんは本家 r7kamura/somemoji を見に行ったほうがいいかもしれません。

middlemanの設定でsomemojiを有効にする

activate :somemoji,
  provider:    'twemoji',
  emojis_dir:  '/images/emoji'

上のコマンドそのまま実行すると設定はこんな風になります。

あと、asset_hashを使っているならemoji画像以下はhashを付けないようにしてください。

# こんなふうに
activate :asset_hash, ignore: 'images/twemoji'

emojiを入力する

😄 🎊 👀 :star: 👍 💤 🈂 🤘

既知の問題点

preのなかも変換する

<pre><code>の中にあるemoji記法も否応なしに<img>タグに変換してしまうので、これを直したいです。見通しは立ってます。手を動かすだけです。

asset_hash対応

これ必要かなぁ…… ❓

よろしくお願いします

🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏 🙏

2017年05月17日
2017年05月12日

mastodonインスタンス、立てたはいいけど不安定

red mastodon

(2017-05-13 10:53 誤字修正)

立てて2週間ほど

こちらになります → lupinus.bouquet.blue

赤い

やぎにいが一晩でやってくれました。 dark pink color theme by yagi2 · Pull Request #3 · unasuke/mastodon

不安定とは

頻繁に500

ALBが頻繁に500を返すので、ログを見たらpumaが起動直後に死んでるのでインスタンスタイプをt2.mediumに上げたら安定しました。

before t2.micro

after t2.medium

streamingが動かない

つらい。

wss can't connect

nodeからpostgresへの接続がうまくいっていないのか、Missing access tokenで怒られている。

DDoS https://lupinus.bouquet.blue/@unasuke/59

他インスタンスから(他インスタンスの)画像が取得できない

mastodon rch

mastodon pawoo

S3のACLはpublicにreadできるはずなのに、何故。

現状

以下、現状(t2.medium)です。

mastodon metrics

2017年05月12日
新しい投稿
古い投稿