ISUCON13参加記 #isucon

created: 2023-11-29

ISUCON13に参加した。

最終的なベンチマークスコアは7000程だった。

リンク

使ったツール

  • percona-toolkit(pt-query-digest)
    • スロークエリの分析
  • alp
    • nginxアクセスログの分析

最終的な構成

  • 1: nginx, app, DB
  • 2: 無
  • 3: 無

やったこと・やろうとしたこと

  • debug=False
  • 1+Nクエリを消す
  • インデックスを追加する
  • スパムコメントの判定をアプリ上で実行する
  • NGワードの登録を直す(未完)
  • DNSデータベースのインデックス追加(revert)
  • アイコン画像をDBから出す(未完)

debug=Falseにする

1+Nクエリを消す

1+Nクエリがあるので直す。

1+N(1+N)クエリになっている箇所を一気に直そうとしてバグらせ続けたので、途中で捨てて一段階ずつ直すことにしてなんとかした。

全て消せたかというとまだ残っていた気がする。

1+Nクエリの検出はソースコードリーディングで頑張った

インデックスを追加する

各テーブルにインデックスが全く存在しないので、user_id, livestream_iあたりのidカラムに全体的に何も考えず追加した。

その後、 log_queries_not_using_indexes を設定して、インデックスを使っていないクエリを眺めつつインデックスを追加した。

initializeによってCREATE TABLEが行われると途中まで思っていたのでschema.sqlにインデックスを追加だけしていたけれど、initializeではTRUNCATE TABLEしか行われないことに気付いたのでinitialize処理中にDROP TABLEとCREATE TABLEを行うようにした。

スパムコメントの判定をアプリ上で実行する

コメントにNGワードが含まれているかの判定をわざわざアプリからDBMSに投げている箇所があったので、アプリ内で実行するようにした。

謎のサブクエリをFROMしたりJOINしたりしていて何をしているのか一見全く解らなかった。

SELECT COUNT(*)
FROM (SELECT %s AS text) AS texts
INNER JOIN (SELECT CONCAT('%%', %s, '%%') AS pattern) AS patterns
ON texts.text LIKE patterns.pattern;

他にも、件数を取得するためにレコードを取得してアプリ上で count している箇所もあったりして、このあたりは意図的に捻って入れた非効率コードの気配があった。

NGワードの登録を直す(未完)

NGワードの登録機能があり、NGワードを登録した時に過去のコメントを全て確認して消したり消さなかったりするのだけれど、登録されたNGワード以外のNGワードも全て再検査していたりして無駄が多く、エンドポイント単位のRTTが大きいので直そうとしていた。

終了の十数秒前くらいにざっくりと実装したけれど、提出には間に合わなかったし、その後確認したところバグっていてFAILしていた。

DNSデータベースにインデックスを追加する

メインのデータベースisupipeにインデックスを追加してしばらく後に、別のデータベース isudns にもインデックスを使っていないクエリがあったのでインデックスを追加した。

DNS問い合わせに使われるデータベースであり、スコアを高めず負荷を増大させるbotのようなリクエスト(DNS水責め)に応えることになってしまってスコアが落ちたのでインデックスは削除した。

インデックスを追加する前の名前解決成功数は5000程度で、インデックス追加後は21000程度になっていた。

アイコン画像をDBから出す(未完)

ISUCONにありがちな、RDBMSの内部にBLOBで画像を持っている実装。

nginxからの配信かアプリからの配信にしたいと思っていたが、時間はなくほとんど手を付けていない。

感想

今年は1人での参加となったけれど、ざっくりとコードを読んでアクセスログ・クエリログを見て改善点を見付けることが少しはできた。

DNS水責め攻撃については全然知らなかったので勉強のきっかけになった。

全体的には遅いポイントを改善することだけを考えていた。

ベンチマークのスコアがどのように上がるのかを読み取れていなかったので、改善の方針が曖昧になっていたかもしれない。今回はtip付きコメントのtipの合計がベンチマークのスコアとなるので、単純にアクセスログからは測れなかった側面がある。 POSTされる内容を見て動作を変えるなどの戦略もあったかもしれない。

過去にはどこのエンドポイントの成功・失敗でスコア加点・減点という単純なルールもあったことに甘えて考えが足りていなかったところだ。