楽しかった

新卒研修の中でパフォーマンスチューニングに取り組んだことはあったが、実際にISUCONに出るのは初めてだった。

今回は株式会社イーグルジャンプ秋葉原ラボとして出場した。

パフォーマンスチューニング

といっても、「パフォーマンスチューニング」と聞いて思いつくような高度なことは自分にはできず、ひたすらN+1と格闘したりDBへのアクセスを減らしたりしていた。

N+1を改善する為にクエリを書き直したら結局LEFT JOIN地獄でむしろスコアが落ちたり

悪あがきとして実行した「一回しか書き込まれないテーブルをグローバル変数にする」作戦で意外とスコアが上がったり

diff --git a/go/app_handlers.go b/go/app_handlers.go
index 2b4fedb..74a22dc 100644
--- a/go/app_handlers.go
+++ b/go/app_handlers.go
@@ -617,12 +617,6 @@ func appPostRideEvaluatation(w http.ResponseWriter, r *http.Request) {
        Amount: fare,
    }
 
-	var paymentGatewayURL string
-	if err := tx.GetContext(ctx, &paymentGatewayURL, "SELECT value FROM settings WHERE name = 'payment_gateway_url'"); err != nil {
-		writeError(w, http.StatusInternalServerError, err)
-		return
-	}
-
    if err := requestPaymentGatewayPostPayment(ctx, paymentGatewayURL, paymentToken.Token, paymentGatewayRequest, func() ([]Ride, error) {
        rides := []Ride{}
        if err := tx.SelectContext(ctx, &rides, `SELECT * FROM rides WHERE user_id = ? ORDER BY created_at ASC`, ride.UserID); err != nil {
diff --git a/go/main.go b/go/main.go
index c058e27..4d498d7 100644
--- a/go/main.go
+++ b/go/main.go
@@ -19,6 +19,7 @@ import (
 )
 
 var db *sqlx.DB
+var paymentGatewayURL string
 
 func main() {
    mux := setup()
@@ -67,6 +68,8 @@ func setup() http.Handler {
    db = _db
 
    mux := chi.NewRouter()
+	// profiler うごかない
+	// mux.Mount("/debug", middleware.Profiler())
    mux.Use(middleware.Logger)
    mux.Use(middleware.Recoverer)
    mux.HandleFunc("POST /api/initialize", postInitialize)
@@ -122,7 +125,6 @@ type postInitializeResponse struct {
 }
 
 func postInitialize(w http.ResponseWriter, r *http.Request) {
-	ctx := r.Context()
    req := &postInitializeRequest{}
    if err := bindJSON(r, req); err != nil {
        writeError(w, http.StatusBadRequest, err)
@@ -134,10 +136,7 @@ func postInitialize(w http.ResponseWriter, r *http.Request) {
        return
    }
 
-	if _, err := db.ExecContext(ctx, "UPDATE settings SET value = ? WHERE name = 'payment_gateway_url'", req.PaymentServer); err != nil {
-		writeError(w, http.StatusInternalServerError, err)
-		return
-	}
+	paymentGatewayURL = req.PaymentServer
 
    writeJSON(w, http.StatusOK, postInitializeResponse{Language: "go"})
 }

これ書いてる時OnceCell欲しくなった。

CTFのA&Dに少し近いけど、それとはまた違った楽しさがあった。

学び

これについてはA&Dと同じで、役割分担とタスクの優先順位付けが重要なんじゃないかと思った。

例えば、ある大きなボトルネックを修正すると別の箇所でDBの負荷が増え、あらたな課題が見つかる。みたいなことがある。

やはりもっと早くprofilerを導入したかったが、なんでchimiddleware.Profiler動かなかったんだろう。Goわからん。

情報セキュリティのCIAにおけるAがAvailabilityであるように、可用性のためのパフォーマンスチューニングはセキュリティエンジニアにも必要な能力かもしれない。

これからはやっていきます。来年も出れたら出たいです。

終わりに

この記事はn01e0 Advent Calendar 2024の8日目の記事とします。