loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request '[GITEA PORT] Do some performance optimize for issues list and view issue/pull (gitea#29515)' (#3116) from oliverpool/forgejo:port_29515 into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3116
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>

+109 -62
+2 -6
models/issues/comment.go
··· 673 673 return err 674 674 } 675 675 676 - func (c *Comment) loadReactions(ctx context.Context, repo *repo_model.Repository) (err error) { 676 + // LoadReactions loads comment reactions 677 + func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository) (err error) { 677 678 if c.Reactions != nil { 678 679 return nil 679 680 } ··· 689 690 return err 690 691 } 691 692 return nil 692 - } 693 - 694 - // LoadReactions loads comment reactions 695 - func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository) error { 696 - return c.loadReactions(ctx, repo) 697 693 } 698 694 699 695 func (c *Comment) loadReview(ctx context.Context) (err error) {
+2 -2
models/issues/comment_code.go
··· 90 90 return pathToLineToComment, nil 91 91 } 92 92 93 - func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, doer *user_model.User, review *Review, showOutdatedComments bool) ([]*Comment, error) { 93 + func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, doer *user_model.User, review *Review, showOutdatedComments bool) (CommentList, error) { 94 94 var comments CommentList 95 95 if review == nil { 96 96 review = &Review{ID: 0} ··· 169 169 } 170 170 171 171 // FetchCodeConversation fetches the code conversation of a given comment (same review, treePath and line number) 172 - func FetchCodeConversation(ctx context.Context, comment *Comment, doer *user_model.User) ([]*Comment, error) { 172 + func FetchCodeConversation(ctx context.Context, comment *Comment, doer *user_model.User) (CommentList, error) { 173 173 opts := FindCommentsOptions{ 174 174 Type: CommentTypeCode, 175 175 IssueID: comment.IssueID,
+57 -19
models/issues/comment_list.go
··· 19 19 func (comments CommentList) getPosterIDs() []int64 { 20 20 posterIDs := make(container.Set[int64], len(comments)) 21 21 for _, comment := range comments { 22 - posterIDs.Add(comment.PosterID) 22 + if comment.PosterID > 0 { 23 + posterIDs.Add(comment.PosterID) 24 + } 23 25 } 24 26 return posterIDs.Values() 25 27 } ··· 41 43 return nil 42 44 } 43 45 44 - func (comments CommentList) getCommentIDs() []int64 { 45 - ids := make([]int64, 0, len(comments)) 46 - for _, comment := range comments { 47 - ids = append(ids, comment.ID) 48 - } 49 - return ids 50 - } 51 - 52 46 func (comments CommentList) getLabelIDs() []int64 { 53 47 ids := make(container.Set[int64], len(comments)) 54 48 for _, comment := range comments { 55 - ids.Add(comment.LabelID) 49 + if comment.LabelID > 0 { 50 + ids.Add(comment.LabelID) 51 + } 56 52 } 57 53 return ids.Values() 58 54 } ··· 100 96 func (comments CommentList) getMilestoneIDs() []int64 { 101 97 ids := make(container.Set[int64], len(comments)) 102 98 for _, comment := range comments { 103 - ids.Add(comment.MilestoneID) 99 + if comment.MilestoneID > 0 { 100 + ids.Add(comment.MilestoneID) 101 + } 104 102 } 105 103 return ids.Values() 106 104 } ··· 141 139 func (comments CommentList) getOldMilestoneIDs() []int64 { 142 140 ids := make(container.Set[int64], len(comments)) 143 141 for _, comment := range comments { 144 - ids.Add(comment.OldMilestoneID) 142 + if comment.OldMilestoneID > 0 { 143 + ids.Add(comment.OldMilestoneID) 144 + } 145 145 } 146 146 return ids.Values() 147 147 } ··· 182 182 func (comments CommentList) getAssigneeIDs() []int64 { 183 183 ids := make(container.Set[int64], len(comments)) 184 184 for _, comment := range comments { 185 - ids.Add(comment.AssigneeID) 185 + if comment.AssigneeID > 0 { 186 + ids.Add(comment.AssigneeID) 187 + } 186 188 } 187 189 return ids.Values() 188 190 } ··· 314 316 if comment.DependentIssue != nil { 315 317 continue 316 318 } 317 - ids.Add(comment.DependentIssueID) 319 + if comment.DependentIssueID > 0 { 320 + ids.Add(comment.DependentIssueID) 321 + } 318 322 } 319 323 return ids.Values() 320 324 } ··· 369 373 return nil 370 374 } 371 375 376 + // getAttachmentCommentIDs only return the comment ids which possibly has attachments 377 + func (comments CommentList) getAttachmentCommentIDs() []int64 { 378 + ids := make(container.Set[int64], len(comments)) 379 + for _, comment := range comments { 380 + if comment.Type.HasAttachmentSupport() { 381 + ids.Add(comment.ID) 382 + } 383 + } 384 + return ids.Values() 385 + } 386 + 387 + // LoadAttachmentsByIssue loads attachments by issue id 388 + func (comments CommentList) LoadAttachmentsByIssue(ctx context.Context) error { 389 + if len(comments) == 0 { 390 + return nil 391 + } 392 + 393 + attachments := make([]*repo_model.Attachment, 0, len(comments)/2) 394 + if err := db.GetEngine(ctx).Where("issue_id=? AND comment_id>0", comments[0].IssueID).Find(&attachments); err != nil { 395 + return err 396 + } 397 + 398 + commentAttachmentsMap := make(map[int64][]*repo_model.Attachment, len(comments)) 399 + for _, attach := range attachments { 400 + commentAttachmentsMap[attach.CommentID] = append(commentAttachmentsMap[attach.CommentID], attach) 401 + } 402 + 403 + for _, comment := range comments { 404 + comment.Attachments = commentAttachmentsMap[comment.ID] 405 + } 406 + return nil 407 + } 408 + 372 409 // LoadAttachments loads attachments 373 410 func (comments CommentList) LoadAttachments(ctx context.Context) (err error) { 374 411 if len(comments) == 0 { ··· 376 413 } 377 414 378 415 attachments := make(map[int64][]*repo_model.Attachment, len(comments)) 379 - commentsIDs := comments.getCommentIDs() 416 + commentsIDs := comments.getAttachmentCommentIDs() 380 417 left := len(commentsIDs) 381 418 for left > 0 { 382 419 limit := db.DefaultMaxInSize 383 420 if left < limit { 384 421 limit = left 385 422 } 386 - rows, err := db.GetEngine(ctx).Table("attachment"). 387 - Join("INNER", "comment", "comment.id = attachment.comment_id"). 388 - In("comment.id", commentsIDs[:limit]). 423 + rows, err := db.GetEngine(ctx). 424 + In("comment_id", commentsIDs[:limit]). 389 425 Rows(new(repo_model.Attachment)) 390 426 if err != nil { 391 427 return err ··· 415 451 func (comments CommentList) getReviewIDs() []int64 { 416 452 ids := make(container.Set[int64], len(comments)) 417 453 for _, comment := range comments { 418 - ids.Add(comment.ReviewID) 454 + if comment.ReviewID > 0 { 455 + ids.Add(comment.ReviewID) 456 + } 419 457 } 420 458 return ids.Values() 421 459 }
+22 -3
models/issues/issue_list.go
··· 391 391 if left < limit { 392 392 limit = left 393 393 } 394 - rows, err := db.GetEngine(ctx).Table("attachment"). 395 - Join("INNER", "issue", "issue.id = attachment.issue_id"). 396 - In("issue.id", issuesIDs[:limit]). 394 + rows, err := db.GetEngine(ctx). 395 + In("issue_id", issuesIDs[:limit]). 397 396 Rows(new(repo_model.Attachment)) 398 397 if err != nil { 399 398 return err ··· 612 611 613 612 return approvalCountMap, nil 614 613 } 614 + 615 + func (issues IssueList) LoadIsRead(ctx context.Context, userID int64) error { 616 + issueIDs := issues.getIssueIDs() 617 + issueUsers := make([]*IssueUser, 0, len(issueIDs)) 618 + if err := db.GetEngine(ctx).Where("uid =?", userID). 619 + In("issue_id", issueIDs). 620 + Find(&issueUsers); err != nil { 621 + return err 622 + } 623 + 624 + for _, issueUser := range issueUsers { 625 + for _, issue := range issues { 626 + if issue.ID == issueUser.IssueID { 627 + issue.IsRead = issueUser.IsRead 628 + } 629 + } 630 + } 631 + 632 + return nil 633 + }
+5
models/issues/issue_list_test.go
··· 72 72 assert.Nil(t, issue.Project) 73 73 } 74 74 } 75 + 76 + assert.NoError(t, issueList.LoadIsRead(db.DefaultContext, 1)) 77 + for _, issue := range issueList { 78 + assert.Equal(t, issue.ID == 1, issue.IsRead, "unexpected is_read value for issue[%d]", issue.ID) 79 + } 75 80 }
+1 -1
models/repo/attachment.go
··· 24 24 IssueID int64 `xorm:"INDEX"` // maybe zero when creating 25 25 ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating 26 26 UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added 27 - CommentID int64 27 + CommentID int64 `xorm:"INDEX"` 28 28 Name string 29 29 DownloadCount int64 `xorm:"DEFAULT 0"` 30 30 Size int64 `xorm:"DEFAULT 0"`
-4
routers/api/v1/repo/issue_comment.go
··· 323 323 ctx.Error(http.StatusInternalServerError, "LoadIssues", err) 324 324 return 325 325 } 326 - if err := comments.LoadPosters(ctx); err != nil { 327 - ctx.Error(http.StatusInternalServerError, "LoadPosters", err) 328 - return 329 - } 330 326 if err := comments.LoadAttachments(ctx); err != nil { 331 327 ctx.Error(http.StatusInternalServerError, "LoadAttachments", err) 332 328 return
+17 -22
routers/web/repo/issue.go
··· 328 328 return 329 329 } 330 330 331 - // Get posters. 332 - for i := range issues { 333 - // Check read status 334 - if !ctx.IsSigned { 335 - issues[i].IsRead = true 336 - } else if err = issues[i].GetIsRead(ctx, ctx.Doer.ID); err != nil { 337 - ctx.ServerError("GetIsRead", err) 331 + if ctx.IsSigned { 332 + if err := issues.LoadIsRead(ctx, ctx.Doer.ID); err != nil { 333 + ctx.ServerError("LoadIsRead", err) 338 334 return 335 + } 336 + } else { 337 + for i := range issues { 338 + issues[i].IsRead = true 339 339 } 340 340 } 341 341 ··· 1602 1602 1603 1603 // Render comments and fetch participants. 1604 1604 participants[0] = issue.Poster 1605 + 1606 + if err := issue.Comments.LoadAttachmentsByIssue(ctx); err != nil { 1607 + ctx.ServerError("LoadAttachmentsByIssue", err) 1608 + return 1609 + } 1610 + if err := issue.Comments.LoadPosters(ctx); err != nil { 1611 + ctx.ServerError("LoadPosters", err) 1612 + return 1613 + } 1614 + 1605 1615 for _, comment = range issue.Comments { 1606 1616 comment.Issue = issue 1607 1617 1608 - if err := comment.LoadPoster(ctx); err != nil { 1609 - ctx.ServerError("LoadPoster", err) 1610 - return 1611 - } 1612 - 1613 1618 if comment.Type == issues_model.CommentTypeComment || comment.Type == issues_model.CommentTypeReview { 1614 - if err := comment.LoadAttachments(ctx); err != nil { 1615 - ctx.ServerError("LoadAttachments", err) 1616 - return 1617 - } 1618 - 1619 1619 comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ 1620 1620 Links: markup.Links{ 1621 1621 Base: ctx.Repo.RepoLink, ··· 1663 1663 comment.Milestone = ghostMilestone 1664 1664 } 1665 1665 } else if comment.Type == issues_model.CommentTypeProject { 1666 - 1667 1666 if err = comment.LoadProject(ctx); err != nil { 1668 1667 ctx.ServerError("LoadProject", err) 1669 1668 return ··· 1729 1728 for _, codeComments := range comment.Review.CodeComments { 1730 1729 for _, lineComments := range codeComments { 1731 1730 for _, c := range lineComments { 1732 - if err := c.LoadAttachments(ctx); err != nil { 1733 - ctx.ServerError("LoadAttachments", err) 1734 - return 1735 - } 1736 1731 // Check tag. 1737 1732 role, ok = marked[c.PosterID] 1738 1733 if ok {
+3 -5
routers/web/repo/pull_review.go
··· 169 169 } 170 170 ctx.Data["PageIsPullFiles"] = (origin == "diff") 171 171 172 - for _, c := range comments { 173 - if err := c.LoadAttachments(ctx); err != nil { 174 - ctx.ServerError("LoadAttachments", err) 175 - return 176 - } 172 + if err := comments.LoadAttachments(ctx); err != nil { 173 + ctx.ServerError("LoadAttachments", err) 174 + return 177 175 } 178 176 179 177 ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled