# ISUCON7予選 ###### tags: `過去問` ## レギュレーション https://isucon.net/archives/50927022.html ## マニュアル https://github.com/isucon/isucon7-qualify isucon1(app) public: 54.178.214.110 private: 172.31.32.90 isucon2(db) public: 54.238.55.143 private: 172.31.34.241 isucon3(nginx) public: 54.64.133.47 private: 172.31.40.208 ベンチ ./bin/bench -remotes=127.0.0.1 -output result.json エラーで落ちる問題 -portalをつけるとなぜか解決する goの最新版インストール チャンネルが10 未読 ユーザー詳細 ユーザー名、表示名、画像 ``` cd ~/local wget https://golang.org/dl/go1.16.5.linux-amd64.tar.gz rm -rf go tar -xzf go1.16.5.linux-amd64.tar.gz ``` ## アプリ概要 ### データベーススキーマ #### User |field|type|desc| |-|-|-| |id|int|key incr| |name|string|unique| |salt|string| |password|string| |display_name|string| |avatar_icon|string|URL?| |created_at|time|| #### Image |field|type|desc| |-|-|-| |id|int|key incr| |name|string|unique| |data|Blob|| #### Channel |field|type|desc| |-|-|-| |id|int|key incr| |name|string|| |description|string|MIDIUMTEXT| |updated_at|time|| |created_at|time|| #### Message |field|type|desc| |-|-|-| |id|int|key| |channel_id|int|| |user_id|int|| |content|text|| |created_at|datetime|not null| #### haveread |field|type|desc| |-|-|-| |user_id|int|key| |channel_id|int|key| |message_id|int|keyいらない?| |updated_at|time|| |created_at|time|| ### エンドポイント |resouce|method|desc| |-|-|-| |/initialize|GET|ベンチマークごとの初期化処理。特定のID以上のデータと既読を削除| |/|GET|ログインしてたらチャンネル1にリダイレクト。そうじゃない場合ウェルカムページ表示| |/register|GET|新規登録ページ| |/register|POST|nameとpasswordで新規登録してセッションにUserIDセット。重複の場合StatusConflict| |/login|GET|ログインページ表示| |/login|POST|userをnameで検索。登録されていないForbidden。salt+pwをsha1してpasswordと比較。セッションにuserIDセット| |/logout|GET|セッションのuserID.session.Save(request, response)?| |/channel/:channel_id **ヤバイ**|GET|ensureLogin(ログインの確認),channelテーブルから**channel全体をOrderby取得して**,そこから**目的のchannel_idをfor-loopで見つける**.最後に取得したchannelを返す| |/message|GET|channel_idのlast_message_id以降のメッセージを一覧取得。jsonifyMessageでUserを1:Nで取得しているので遅い。havereadの最新のmessage_idのupdated_atをnowにして既読判定?| |/message|POST|ログイン確認、チャンネルにメッセージを追加| |/fetch|GET|チャンネルごとの未読の数を一覧で取得する。謎の1秒sleep。channel一覧取得。ユーザーチャンネルのペアごとにhavereadを見て最新のmessage_idを取得して、それ以降のmessageの数をmessageにcountクエリして取得している| |/history/:channel_id|GET|ログイン確認。1ページは20件。毎回チャンネルのメッセージ総数をクエリしてるので遅そう。OFFSE使ってるので遅い。jsonifyMessageのユーザー結合でもロス出てる。チャンネル一覧取得も(横のチャンネル一覧表示するため?)| |/profile/:user_name|GET|ログイン確認、チャンネル一覧取得。userをnameで検索して取得。自分かどうか(self or other)で分岐処理あり| |/profile|POST|ログイン確認、イメージがある場合はLastIndexBytesでファイルネームから拡張子取得、fileからreadしてバイナリ取得して、sha1したやつを拡張子に連結してファイル名としてimageに保存。avatarNameをavatar_iconとしてuser更新。display_nameとupdateも別クエリでやってるので改善の余地あり。nameはidでいい| |/add_channel|GET|ログインの確認,channelテーブルから**idでソートして** channelを取得.channelからテンプレート生成して返す.| |/add_channel|POST|ログインの確認,フォームからname,descriptionを受け取って,channelテーブルにレコードを追加./channel/にリダイレクトする| |/icons/:file_name|GET|imageからfile_nameで検索,name, data取得| 画像をnginxでキャッシュして返す メッセージ:ユーザーの1:N 1. post profile 2. get icons/ 3. get message ## ryunosuke `./bin/bench --remotes=35.75.211.183,35.75.208.108 --portal=localhost -output result.json` ` cat webapp/isucon1/nginx/log/access.log | alp ltsv -m "/history/[0-9a-zA-Z]+,/profile/[0-9a-zA-Z]+,/icons/[0-9a-zA-Z],/channel/[0-9a-zA-Z]" --sort avg -r > results/{tag}.alp` ` cat webapp/isucon2/nginx/log/access.log | alp ltsv -m "/history/[0-9a-zA-Z]+,/profile/[0-9a-zA-Z]+,/icons/[0-9a-zA-Z],/channel/[0-9a-zA-Z]" --sort avg -r > results/{tag}.alp` ### app git pull origin master cd go && go build -o isuabta sudo systemctl restart isubata.golang.service iconをファイルで保存 5000 -> 10000 iconをnginxでキャッシュ 10000 -> 20000 unreadをキャッシュしてfetch改善 20000 -> 50000 fetchにtime sleep追加 50000 -> 90000 (ただしスコアにかなりバラつきあり) sleepを長くしたりランダムにしたり色々試してみたけどダメ --- ネットワーク問題解消(fetchUnreadキャッシュ済み) isucon1: nginx, app(profileのみ) isucon2: app isucon3: mysql で156712 messageの1:N解消で400000
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up