Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getLivestreamStatisticsHandler n+1 #20

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

cureseven
Copy link
Member

#16

ROUTINE ======================== main.getLivestreamStatisticsHandler in /home/isucon/isucon13-onaka-no-owari/webapp/go/stats_handler.go
         0    103.03s (flat, cum)  3.14% of Total
         .          .    231:   if err != nil {
         .          .    232:           return echo.NewHTTPError(http.StatusBadRequest, "livestream_id in path must be integer")
         .          .    233:   }
         .          .    234:   livestreamID := int64(id)
         .          .    235:
         .    20.20ms    236:   tx, err := dbConn.BeginTxx(ctx, nil)
         .          .    237:   if err != nil {
         .          .    238:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to begin transaction: "+err.Error())
         .          .    239:   }
         .          .    240:   defer tx.Rollback()
         .          .    241:
         .          .    242:   var livestream LivestreamModel
         .          .    243:   if err := tx.GetContext(ctx, &livestream, "SELECT * FROM livestreams WHERE id = ?", livestreamID); err != nil {
         .          .    244:           if errors.Is(err, sql.ErrNoRows) {
         .          .    245:                   return echo.NewHTTPError(http.StatusBadRequest, "cannot get stats of not found livestream")
         .          .    246:           } else {
         .          .    247:                   return echo.NewHTTPError(http.StatusInternalServerError, "failed to get livestream: "+err.Error())
         .          .    248:           }
         .          .    249:   }
         .          .    250:
         .          .    251:   var livestreams []*LivestreamModel
         .   343.43ms    252:   if err := tx.SelectContext(ctx, &livestreams, "SELECT * FROM livestreams"); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    253:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to get livestreams: "+err.Error())
         .          .    254:   }
         .          .    255:
         .          .    256:   // ランク算出
         .          .    257:   var ranking LivestreamRanking
         .          .    258:   for _, livestream := range livestreams {
         .          .    259:           var reactions int64
         .     64.15s    260:           if err := tx.GetContext(ctx, &reactions, "SELECT COUNT(*) FROM livestreams l INNER JOIN reactions r ON l.id = r.livestream_id WHERE l.id = ?", livestream.ID); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    261:                   return echo.NewHTTPError(http.StatusInternalServerError, "failed to count reactions: "+err.Error())
         .          .    262:           }
         .          .    263:
         .    20.20ms    264:           var totalTips int64
         .     38.48s    265:           if err := tx.GetContext(ctx, &totalTips, "SELECT IFNULL(SUM(l2.tip), 0) FROM livestreams l INNER JOIN livecomments l2 ON l.id = l2.livestream_id WHERE l.id = ?", livestream.ID); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    266:                   return echo.NewHTTPError(http.StatusInternalServerError, "failed to count tips: "+err.Error())
         .          .    267:           }
         .          .    268:
         .          .    269:           score := reactions + totalTips
         .          .    270:           ranking = append(ranking, LivestreamRankingEntry{
         .          .    271:                   LivestreamID: livestream.ID,
         .          .    272:                   Score:        score,
         .          .    273:           })
         .          .    274:   }
         .          .    275:   sort.Sort(ranking)
         .          .    276:
         .          .    277:   var rank int64 = 1
         .          .    278:   for i := len(ranking) - 1; i >= 0; i-- {
         .          .    279:           entry := ranking[i]
         .          .    280:           if entry.LivestreamID == livestreamID {
         .          .    281:                   break
         .          .    282:           }
         .          .    283:           rank++
         .          .    284:   }
         .          .    285:
         .          .    286:   // 視聴者数算出
         .          .    287:   var viewersCount int64
         .          .    288:   if err := tx.GetContext(ctx, &viewersCount, `SELECT COUNT(*) FROM livestreams l INNER JOIN livestream_viewers_history h ON h.livestream_id = l.id WHERE l.id = ?`, livestreamID); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    289:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to count livestream viewers: "+err.Error())
         .          .    290:   }
         .          .    291:
         .          .    292:   // 最大チップ額
         .          .    293:   var maxTip int64
         .          .    294:   if err := tx.GetContext(ctx, &maxTip, `SELECT IFNULL(MAX(tip), 0) FROM livestreams l INNER JOIN livecomments l2 ON l2.livestream_id = l.id WHERE l.id = ?`, livestreamID); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    295:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to find maximum tip livecomment: "+err.Error())
         .          .    296:   }
         .          .    297:
         .          .    298:   // リアクション数
         .          .    299:   var totalReactions int64
         .          .    300:   if err := tx.GetContext(ctx, &totalReactions, "SELECT COUNT(*) FROM livestreams l INNER JOIN reactions r ON r.livestream_id = l.id WHERE l.id = ?", livestreamID); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    301:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to count total reactions: "+err.Error())
         .          .    302:   }
         .          .    303:
         .          .    304:   // スパム報告数
         .          .    305:   var totalReports int64
         .    10.10ms    306:   if err := tx.GetContext(ctx, &totalReports, `SELECT COUNT(*) FROM livestreams l INNER JOIN livecomment_reports r ON r.livestream_id = l.id WHERE l.id = ?`, livestreamID); err != nil && !errors.Is(err, sql.ErrNoRows) {
         .          .    307:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to count total spam reports: "+err.Error())
         .          .    308:   }
         .          .    309:
         .          .    310:   if err := tx.Commit(); err != nil {
         .          .    311:           return echo.NewHTTPError(http.StatusInternalServerError, "failed to commit: "+err.Error())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant