It takes a long time to open a big pull request page #6897

Closed
opened 2025-11-02 07:10:25 -06:00 by GiteaMirror · 35 comments
Owner

Originally created by @ffbh123456 on GitHub (Feb 18, 2021).

Gitea version 1.14.0+dev-449-ge0c753e77 built with GNU Make 4.3, go1.15.6 : bindata, timetzdata, sqlite, sqlite_unlock_notify

The gitea server is deployed locally. I made a pull request and changed more than 100 files and more than 1,000 lines. It took me nearly two minutes to open this pull request page.
I looked at the log, mainly because these two API return very slowly, both of which are about one minute
Are there any configuration items that can improve the speed here?
image

Originally created by @ffbh123456 on GitHub (Feb 18, 2021). Gitea version 1.14.0+dev-449-ge0c753e77 built with GNU Make 4.3, go1.15.6 : bindata, timetzdata, sqlite, sqlite_unlock_notify The gitea server is deployed locally. I made a pull request and changed more than 100 files and more than 1,000 lines. It took me nearly two minutes to open this pull request page. I looked at the log, mainly because these two API return very slowly, both of which are about one minute Are there any configuration items that can improve the speed here? ![image](https://user-images.githubusercontent.com/20750357/108376101-95feb000-723d-11eb-9884-cbad07d0ebf6.png)
GiteaMirror added the performance/speed label 2025-11-02 07:10:25 -06:00
Author
Owner

@lunny commented on GitHub (Feb 18, 2021):

How many files and lines changed on this PR?

@lunny commented on GitHub (Feb 18, 2021): How many files and lines changed on this PR?
Author
Owner

@tomaswarynyca commented on GitHub (Feb 18, 2021):

An example https://gitea.com/gitea/tea/pulls/316/files

I think you should put a limit to the amount of content displayed and if the user requires more by clicking on a button to load more content.

@tomaswarynyca commented on GitHub (Feb 18, 2021): An example https://gitea.com/gitea/tea/pulls/316/files I think you should put a limit to the amount of content displayed and if the user requires more by clicking on a button to load more content.
Author
Owner

@ffbh123456 commented on GitHub (Feb 19, 2021):

@lunny
100 file, 1000 add line, 1000 delete line, every file about 10 add line and 10 delete line.

@ffbh123456 commented on GitHub (Feb 19, 2021): @lunny 100 file, 1000 add line, 1000 delete line, every file about 10 add line and 10 delete line.
Author
Owner

@PhenX commented on GitHub (Feb 19, 2021):

I agree that the pull request page can be very hard to use, even more when dealing with many files. One solution would be to show a tree of the modified files and show the diff when clicking on those files. We had this on bitbucket and that was really better than to have everything on the same page.
This would solve the problem for this kind of pull request, and I personally find it way better.
All my colleagues agree with this, they miss this feature.

@PhenX commented on GitHub (Feb 19, 2021): I agree that the pull request page can be very hard to use, even more when dealing with many files. One solution would be to show a tree of the modified files and show the diff when clicking on those files. We had this on bitbucket and that was really better than to have everything on the same page. This would solve the problem for this kind of pull request, and I personally find it way better. All my colleagues agree with this, they miss this feature.
Author
Owner

@bartkaptur commented on GitHub (Feb 20, 2021):

Same problem here. Setting DISABLE_DIFF_HIGHLIGHT = true helps, but only gets you so far. The HTML generated for a pull request is highly complicated and gets huge quickly. A new, simplified mode for this view would be useful.

@bartkaptur commented on GitHub (Feb 20, 2021): Same problem here. Setting DISABLE_DIFF_HIGHLIGHT = true helps, but only gets you so far. The HTML generated for a pull request is highly complicated and gets huge quickly. A new, simplified mode for this view would be useful.
Author
Owner

@primesun commented on GitHub (May 8, 2021):

In my opinion the ideal solution would be to have a file tree on the pull request page, and you would click to select one file diff at a time.

@primesun commented on GitHub (May 8, 2021): In my opinion the ideal solution would be to have a file tree on the pull request page, and you would click to select one file diff at a time.
Author
Owner

@PhenX commented on GitHub (May 10, 2021):

Hello, to follow up on my last message about the pull request page, I started a project built on AspNet Core (5.0, but might work easily on 3.1 or even 2.1 as the backend is rather simple, no database required, everything is done via API) and VueJS for the front end.

It uses the Gitea API to provide :

  • Authentication
  • A list of the connected user's accessible pull requests or only the ones for which he's a reviewer
  • A GUI with a tree of the PR files
  • A diff based on Monaco Editor (side by side view or unified)
  • Ability to view/add comments on the files
  • Approve / Reject / Comment buttons
  • Previous diff / next diff buttons
  • A viewed / not viewed status for each file (via localStorage)
  • All in a single page, no page reload required, etc
  • Dark theme

I'm planning to release it as open source when I think it's less buggy, but a few members of my team already use it (I do everyday).

Here is what it loooks like :
image

@PhenX commented on GitHub (May 10, 2021): Hello, to follow up on my last message about the pull request page, I started a project built on AspNet Core (5.0, but might work easily on 3.1 or even 2.1 as the backend is rather simple, no database required, everything is done via API) and VueJS for the front end. It uses the Gitea API to provide : * Authentication * A list of the connected user's accessible pull requests or only the ones for which he's a reviewer * A GUI with a tree of the PR files * A diff based on Monaco Editor (side by side view or unified) * Ability to view/add comments on the files * Approve / Reject / Comment buttons * Previous diff / next diff buttons * A viewed / not viewed status for each file (via localStorage) * All in a single page, no page reload required, etc * Dark theme I'm planning to release it as open source when I think it's less buggy, but a few members of my team already use it (I do everyday). Here is what it loooks like : ![image](https://user-images.githubusercontent.com/42170/117616887-085f9c00-b16c-11eb-9c9c-0aa34904fd86.png)
Author
Owner

@zeripath commented on GitHub (May 11, 2021):

Yes this is a known problem.

I know how to solve it but I still haven't been able to get round to it.

We need to make the diff page in sections and farm parts of it off to Ajax and other requests.

@zeripath commented on GitHub (May 11, 2021): Yes this is a known problem. I know how to solve it but I still haven't been able to get round to it. We need to make the diff page in sections and farm parts of it off to Ajax and other requests.
Author
Owner

@typeless commented on GitHub (Jun 9, 2021):

I have seen this issue too.
The bottleneck appears to be in the syntax highlight library.

I sampled the stack trace when my Gitea was hanging on showing pull diffs and got the following:

goroutine 396662 [runnable]:
github.com/danwakefield/fnmatch.Match(0x2a0e726, 0x4, 0xc012b7b520, 0x17, 0x0, 0xc00c773900)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/danwakefield/fnmatch/fnmatch.go:39 +0x78c
github.com/danwakefield/fnmatch.Match(0x2a0e726, 0x4, 0xc012b7b51d, 0x1a, 0x0, 0xc00c773900)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/danwakefield/fnmatch/fnmatch.go:108 +0x33f
github.com/alecthomas/chroma/lexers/internal.Match(0xc012b7b51d, 0x1a, 0xc012b7b535, 0x2)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/alecthomas/chroma/lexers/internal/api.go:94 +0x4fb
github.com/alecthomas/chroma/lexers.Match(...)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/alecthomas/chroma/lexers/lexers.go:51
code.gitea.io/gitea/modules/highlight.Code(0xc012b7b4a3, 0x94, 0xc014ce4781, 0x70, 0xc00b045a50, 0x40f13b)
	/home/mural/src/code.gitea.io/gitea/modules/highlight/highlight.go:77 +0x5af
code.gitea.io/gitea/services/gitdiff.(*DiffSection).GetComputedInlineDiffFor(0xc0131ed100, 0xc01349a140, 0x0, 0x0)
	/home/mural/src/code.gitea.io/gitea/services/gitdiff/gitdiff.go:551 +0x64c
reflect.Value.call(0x26a21e0, 0xc0131ed100, 0x213, 0x2a04a2d, 0x4, 0xc00c777578, 0x1, 0x1, 0xc013477cd8, 0x196, ...)
	/home/mural/src/golang.org/go1.16.3/src/reflect/value.go:476 +0x8e7
reflect.Value.Call(0x26a21e0, 0xc0131ed100, 0x213, 0xc00c777578, 0x1, 0x1, 0xc015ac5400, 0x27ae020, 0xc013477cd8)
	/home/mural/src/golang.org/go1.16.3/src/reflect/value.go:337 +0xb9
text/template.safeCall(0x26a21e0, 0xc0131ed100, 0x213, 0xc00c777578, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, ...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/funcs.go:365 +0xbd
text/template.(*state).evalCall(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x26a21e0, 0xc0131ed100, 0x213, 0x3f94dd0, 0xc00b227050, 0xc005f94969, ...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:725 +0x689
text/template.(*state).evalField(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc005f94969, 0x18, 0x3f94dd0, 0xc00b227050, 0xc0084472a0, 0x2, ...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:609 +0xbf1
text/template.(*state).evalFieldChain(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x26a21e0, 0xc013313400, 0x196, 0x3f94dd0, 0xc00b227050, 0xc008447290, ...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:570 +0x225
text/template.(*state).evalVariableNode(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b227050, 0xc0084472a0, 0x2, 0x2, 0x2698d20, 0x56a2da8, ...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:558 +0x2cc
text/template.(*state).evalCommand(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b226ff0, 0x2698d20, 0x56a2da8, 0x99, 0xc00b046ec8, 0x6, ...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:473 +0x825
text/template.(*state).evalPipeline(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc00ae9bec0, 0x0, 0x0, 0x0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:436 +0x125
text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f948c0, 0xc00b2270b0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:255 +0x38a
text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b90, 0xc00b226270)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b046ec8, 0xa, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b1ff8c0, 0xc00b5b49f0, 0xc00b226270)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b48, 0xc00981e880)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b90, 0xc00b45c7b0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b046ec8, 0xa, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b1fe9c0, 0xc00b45c7b0, 0x0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:294 +0x206
text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b48, 0xc00981eb00)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b90, 0xc00b45c5d0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkRange.func1(0x25a3b40, 0xc00c76f3b8, 0x82, 0x27ae020, 0xc013477cd8, 0x196)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:351 +0x125
text/template.(*state).walkRange(0xc00b046ec8, 0x26a21e0, 0xc013313400, 0x196, 0xc00981eb80)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:360 +0x2f8
text/template.(*state).walk(0xc00b046ec8, 0x26a21e0, 0xc013313400, 0x196, 0x3f94cb0, 0xc00981eb80)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:267 +0x445
text/template.(*state).walk(0xc00b046ec8, 0x26a21e0, 0xc013313400, 0x196, 0x3f94b90, 0xc00b45c480)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkRange.func1(0x25a3b40, 0x54e4740, 0x82, 0x26a21e0, 0xc013313400, 0x196)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:351 +0x125
text/template.(*state).walkRange(0xc00b046ec8, 0x267f400, 0xc017687098, 0x95, 0xc00981ec00)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:360 +0x2f8
text/template.(*state).walk(0xc00b046ec8, 0x267f400, 0xc017687098, 0x95, 0x3f94cb0, 0xc00981ec00)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:267 +0x445
text/template.(*state).walk(0xc00b046ec8, 0x267f400, 0xc017687098, 0x95, 0x3f94b90, 0xc00b45c270)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkTemplate(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0xc00515cc40)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:418 +0x225
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94d40, 0xc00515cc40)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:269 +0x205
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc01e97e450)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x26a2160, 0xc0138f9d80, 0x196, 0xc00a10f020, 0xc01e97e330, 0xc01e97e450)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b48, 0xc00515cd40)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc01e97e240)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x26a2160, 0xc0138f9d80, 0x196, 0xc00a10ef60, 0xc01e97e0c0, 0xc01e97e240)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b48, 0xc00515ce40)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc00d9a32f0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x26a2160, 0xc0138f9d80, 0x196, 0xc009e47980, 0xc006632e40, 0xc00d9a32f0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b48, 0xc004fafc80)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc006632d50)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkRange.func1(0x25a3b40, 0x54e48c0, 0x82, 0x26a2160, 0xc0138f9d80, 0x196)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:351 +0x125
text/template.(*state).walkRange(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0xc004fafd00)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:360 +0x2f8
text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94cb0, 0xc004fafd00)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:267 +0x445
text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc009373dd0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc009e47080, 0xc009373860, 0xc009373dd0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc006bc6440)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc0093737d0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkTemplate(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00caed680)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:418 +0x225
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94d40, 0xc00caed680)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:269 +0x205
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c0465a0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b048168, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00c0390e0, 0xc00c0462d0, 0xc00c0465a0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc00caed6c0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c046210)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b048168, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00c038fc0, 0xc00c046210, 0xc00c101c80)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:294 +0x206
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc00caed8c0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c0460c0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*state).walkIfOrWith(0xc00b048168, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00c088a20, 0xc00c08ab40, 0xc00c0460c0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc00caed900)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285
text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c020f30)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c
text/template.(*Template).execute(0xc00c9c67c0, 0x3f52860, 0xc00f0e22a0, 0x267f400, 0xc00e1d6e70, 0x0, 0x0)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:220 +0x1c6
text/template.(*Template).Execute(...)
	/home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:203
html/template.(*Template).ExecuteTemplate(0xc0067ce450, 0x3f52860, 0xc00f0e22a0, 0x2b227cb, 0x11, 0x267f400, 0xc00e1d6e70, 0x18, 0xc00bbd8bd0)
	/home/mural/src/golang.org/go1.16.3/src/html/template/template.go:139 +0xab
github.com/unrolled/render.HTML.Render(0xc00bbd8bd0, 0x18, 0xc8, 0x2b227cb, 0x11, 0xc0067ce450, 0x3f70af8, 0xc005d11ce0, 0x7fa1b77475f0, 0xc00e17ba80, ...)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/unrolled/render/engine.go:94 +0xb1
github.com/unrolled/render.(*Render).Render(0xc004722f00, 0x7fa1b77475f0, 0xc00e17ba80, 0x3f59340, 0xc00ce2d940, 0x267f400, 0xc00e1d6e70, 0x0, 0x0)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/unrolled/render/render.go:377 +0x6c
github.com/unrolled/render.(*Render).HTML(0xc004722f00, 0x7fa1b77475f0, 0xc00e17ba80, 0xc8, 0x2b227cb, 0x11, 0x267f400, 0xc00e1d6e70, 0x0, 0x0, ...)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/unrolled/render/render.go:433 +0x325
code.gitea.io/gitea/modules/context.(*Context).HTML(0xc01fa77200, 0xc8, 0x2b227cb, 0x11)
	/home/mural/src/code.gitea.io/gitea/modules/context/context.go:189 +0x270
code.gitea.io/gitea/routers/repo.CompareDiff(0xc01fa77200)
	/home/mural/src/code.gitea.io/gitea/routers/repo/compare.go:677 +0xd70
code.gitea.io/gitea/modules/web.Wrap.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/code.gitea.io/gitea/modules/web/route.go:64 +0x1dc
net/http.HandlerFunc.ServeHTTP(0xc007858e80, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc007844d80, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:436 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00755df00, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
code.gitea.io/gitea/modules/web.Middle.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/code.gitea.io/gitea/modules/web/route.go:103 +0x137
net/http.HandlerFunc.ServeHTTP(0xc0078427c0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
code.gitea.io/gitea/modules/web.Middle.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/code.gitea.io/gitea/modules/web/route.go:103 +0x137
net/http.HandlerFunc.ServeHTTP(0xc0078427e0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
code.gitea.io/gitea/modules/web.Middle.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/code.gitea.io/gitea/modules/web/route.go:103 +0x137
net/http.HandlerFunc.ServeHTTP(0xc007842800, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi/middleware.GetHead.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/middleware/get_head.go:37 +0x182
net/http.HandlerFunc.ServeHTTP(0xc003c41248, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
code.gitea.io/gitea/modules/context.Contexter.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/code.gitea.io/gitea/modules/context/context.go:751 +0x1dca
net/http.HandlerFunc.ServeHTTP(0xc0078474a0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc007844d80, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:70 +0x5ab
github.com/go-chi/chi.(*Mux).Mount.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:311 +0x17c
net/http.HandlerFunc.ServeHTTP(0xc0078dfd40, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc004728f00, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:436 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc005c8db90, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
code.gitea.io/gitea/routers/routes.Recovery.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/code.gitea.io/gitea/routers/routes/base.go:211 +0x91
net/http.HandlerFunc.ServeHTTP(0xc005ca92c0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
gitea.com/go-chi/session.Sessioner.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/code.gitea.io/gitea/vendor/gitea.com/go-chi/session/session.go:256 +0x24f
net/http.HandlerFunc.ServeHTTP(0xc005ca92e0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
code.gitea.io/gitea/modules/public.AssetsHandler.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/code.gitea.io/gitea/modules/public/public.go:42 +0x8f
net/http.HandlerFunc.ServeHTTP(0xc005cd0ab0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc004728f00, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:70 +0x5ab
github.com/go-chi/chi.(*Mux).Mount.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:311 +0x17c
net/http.HandlerFunc.ServeHTTP(0xc0078dfd60, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500)
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44
created by net/http.(*Server).Serve
	/home/mural/src/golang.org/go1.16.3/src/net/http/server.go:3013 +0x39b

圖片

@typeless commented on GitHub (Jun 9, 2021): I have seen this issue too. The bottleneck appears to be in the syntax highlight library. I sampled the stack trace when my Gitea was hanging on showing pull diffs and got the following: ``` goroutine 396662 [runnable]: github.com/danwakefield/fnmatch.Match(0x2a0e726, 0x4, 0xc012b7b520, 0x17, 0x0, 0xc00c773900) /home/mural/src/code.gitea.io/gitea/vendor/github.com/danwakefield/fnmatch/fnmatch.go:39 +0x78c github.com/danwakefield/fnmatch.Match(0x2a0e726, 0x4, 0xc012b7b51d, 0x1a, 0x0, 0xc00c773900) /home/mural/src/code.gitea.io/gitea/vendor/github.com/danwakefield/fnmatch/fnmatch.go:108 +0x33f github.com/alecthomas/chroma/lexers/internal.Match(0xc012b7b51d, 0x1a, 0xc012b7b535, 0x2) /home/mural/src/code.gitea.io/gitea/vendor/github.com/alecthomas/chroma/lexers/internal/api.go:94 +0x4fb github.com/alecthomas/chroma/lexers.Match(...) /home/mural/src/code.gitea.io/gitea/vendor/github.com/alecthomas/chroma/lexers/lexers.go:51 code.gitea.io/gitea/modules/highlight.Code(0xc012b7b4a3, 0x94, 0xc014ce4781, 0x70, 0xc00b045a50, 0x40f13b) /home/mural/src/code.gitea.io/gitea/modules/highlight/highlight.go:77 +0x5af code.gitea.io/gitea/services/gitdiff.(*DiffSection).GetComputedInlineDiffFor(0xc0131ed100, 0xc01349a140, 0x0, 0x0) /home/mural/src/code.gitea.io/gitea/services/gitdiff/gitdiff.go:551 +0x64c reflect.Value.call(0x26a21e0, 0xc0131ed100, 0x213, 0x2a04a2d, 0x4, 0xc00c777578, 0x1, 0x1, 0xc013477cd8, 0x196, ...) /home/mural/src/golang.org/go1.16.3/src/reflect/value.go:476 +0x8e7 reflect.Value.Call(0x26a21e0, 0xc0131ed100, 0x213, 0xc00c777578, 0x1, 0x1, 0xc015ac5400, 0x27ae020, 0xc013477cd8) /home/mural/src/golang.org/go1.16.3/src/reflect/value.go:337 +0xb9 text/template.safeCall(0x26a21e0, 0xc0131ed100, 0x213, 0xc00c777578, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, ...) /home/mural/src/golang.org/go1.16.3/src/text/template/funcs.go:365 +0xbd text/template.(*state).evalCall(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x26a21e0, 0xc0131ed100, 0x213, 0x3f94dd0, 0xc00b227050, 0xc005f94969, ...) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:725 +0x689 text/template.(*state).evalField(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc005f94969, 0x18, 0x3f94dd0, 0xc00b227050, 0xc0084472a0, 0x2, ...) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:609 +0xbf1 text/template.(*state).evalFieldChain(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x26a21e0, 0xc013313400, 0x196, 0x3f94dd0, 0xc00b227050, 0xc008447290, ...) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:570 +0x225 text/template.(*state).evalVariableNode(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b227050, 0xc0084472a0, 0x2, 0x2, 0x2698d20, 0x56a2da8, ...) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:558 +0x2cc text/template.(*state).evalCommand(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b226ff0, 0x2698d20, 0x56a2da8, 0x99, 0xc00b046ec8, 0x6, ...) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:473 +0x825 text/template.(*state).evalPipeline(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0xc00ae9bec0, 0x0, 0x0, 0x0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:436 +0x125 text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f948c0, 0xc00b2270b0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:255 +0x38a text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b90, 0xc00b226270) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b046ec8, 0xa, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b1ff8c0, 0xc00b5b49f0, 0xc00b226270) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b48, 0xc00981e880) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b90, 0xc00b45c7b0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b046ec8, 0xa, 0x27ae020, 0xc013477cd8, 0x196, 0xc00b1fe9c0, 0xc00b45c7b0, 0x0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:294 +0x206 text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b48, 0xc00981eb00) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b046ec8, 0x27ae020, 0xc013477cd8, 0x196, 0x3f94b90, 0xc00b45c5d0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkRange.func1(0x25a3b40, 0xc00c76f3b8, 0x82, 0x27ae020, 0xc013477cd8, 0x196) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:351 +0x125 text/template.(*state).walkRange(0xc00b046ec8, 0x26a21e0, 0xc013313400, 0x196, 0xc00981eb80) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:360 +0x2f8 text/template.(*state).walk(0xc00b046ec8, 0x26a21e0, 0xc013313400, 0x196, 0x3f94cb0, 0xc00981eb80) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:267 +0x445 text/template.(*state).walk(0xc00b046ec8, 0x26a21e0, 0xc013313400, 0x196, 0x3f94b90, 0xc00b45c480) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkRange.func1(0x25a3b40, 0x54e4740, 0x82, 0x26a21e0, 0xc013313400, 0x196) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:351 +0x125 text/template.(*state).walkRange(0xc00b046ec8, 0x267f400, 0xc017687098, 0x95, 0xc00981ec00) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:360 +0x2f8 text/template.(*state).walk(0xc00b046ec8, 0x267f400, 0xc017687098, 0x95, 0x3f94cb0, 0xc00981ec00) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:267 +0x445 text/template.(*state).walk(0xc00b046ec8, 0x267f400, 0xc017687098, 0x95, 0x3f94b90, 0xc00b45c270) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkTemplate(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0xc00515cc40) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:418 +0x225 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94d40, 0xc00515cc40) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:269 +0x205 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc01e97e450) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x26a2160, 0xc0138f9d80, 0x196, 0xc00a10f020, 0xc01e97e330, 0xc01e97e450) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b48, 0xc00515cd40) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc01e97e240) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x26a2160, 0xc0138f9d80, 0x196, 0xc00a10ef60, 0xc01e97e0c0, 0xc01e97e240) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b48, 0xc00515ce40) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc00d9a32f0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x26a2160, 0xc0138f9d80, 0x196, 0xc009e47980, 0xc006632e40, 0xc00d9a32f0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b48, 0xc004fafc80) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b047a50, 0x26a2160, 0xc0138f9d80, 0x196, 0x3f94b90, 0xc006632d50) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkRange.func1(0x25a3b40, 0x54e48c0, 0x82, 0x26a2160, 0xc0138f9d80, 0x196) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:351 +0x125 text/template.(*state).walkRange(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0xc004fafd00) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:360 +0x2f8 text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94cb0, 0xc004fafd00) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:267 +0x445 text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc009373dd0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b047a50, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc009e47080, 0xc009373860, 0xc009373dd0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc006bc6440) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b047a50, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc0093737d0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkTemplate(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00caed680) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:418 +0x225 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94d40, 0xc00caed680) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:269 +0x205 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c0465a0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b048168, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00c0390e0, 0xc00c0462d0, 0xc00c0465a0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc00caed6c0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c046210) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b048168, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00c038fc0, 0xc00c046210, 0xc00c101c80) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:294 +0x206 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc00caed8c0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c0460c0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*state).walkIfOrWith(0xc00b048168, 0xa, 0x267f400, 0xc00e1d6e70, 0x15, 0xc00c088a20, 0xc00c08ab40, 0xc00c0460c0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:297 +0x265 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b48, 0xc00caed900) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:261 +0x285 text/template.(*state).walk(0xc00b048168, 0x267f400, 0xc00e1d6e70, 0x15, 0x3f94b90, 0xc00c020f30) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:264 +0x13c text/template.(*Template).execute(0xc00c9c67c0, 0x3f52860, 0xc00f0e22a0, 0x267f400, 0xc00e1d6e70, 0x0, 0x0) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:220 +0x1c6 text/template.(*Template).Execute(...) /home/mural/src/golang.org/go1.16.3/src/text/template/exec.go:203 html/template.(*Template).ExecuteTemplate(0xc0067ce450, 0x3f52860, 0xc00f0e22a0, 0x2b227cb, 0x11, 0x267f400, 0xc00e1d6e70, 0x18, 0xc00bbd8bd0) /home/mural/src/golang.org/go1.16.3/src/html/template/template.go:139 +0xab github.com/unrolled/render.HTML.Render(0xc00bbd8bd0, 0x18, 0xc8, 0x2b227cb, 0x11, 0xc0067ce450, 0x3f70af8, 0xc005d11ce0, 0x7fa1b77475f0, 0xc00e17ba80, ...) /home/mural/src/code.gitea.io/gitea/vendor/github.com/unrolled/render/engine.go:94 +0xb1 github.com/unrolled/render.(*Render).Render(0xc004722f00, 0x7fa1b77475f0, 0xc00e17ba80, 0x3f59340, 0xc00ce2d940, 0x267f400, 0xc00e1d6e70, 0x0, 0x0) /home/mural/src/code.gitea.io/gitea/vendor/github.com/unrolled/render/render.go:377 +0x6c github.com/unrolled/render.(*Render).HTML(0xc004722f00, 0x7fa1b77475f0, 0xc00e17ba80, 0xc8, 0x2b227cb, 0x11, 0x267f400, 0xc00e1d6e70, 0x0, 0x0, ...) /home/mural/src/code.gitea.io/gitea/vendor/github.com/unrolled/render/render.go:433 +0x325 code.gitea.io/gitea/modules/context.(*Context).HTML(0xc01fa77200, 0xc8, 0x2b227cb, 0x11) /home/mural/src/code.gitea.io/gitea/modules/context/context.go:189 +0x270 code.gitea.io/gitea/routers/repo.CompareDiff(0xc01fa77200) /home/mural/src/code.gitea.io/gitea/routers/repo/compare.go:677 +0xd70 code.gitea.io/gitea/modules/web.Wrap.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/code.gitea.io/gitea/modules/web/route.go:64 +0x1dc net/http.HandlerFunc.ServeHTTP(0xc007858e80, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 github.com/go-chi/chi.(*Mux).routeHTTP(0xc007844d80, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:436 +0x28b net/http.HandlerFunc.ServeHTTP(0xc00755df00, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 code.gitea.io/gitea/modules/web.Middle.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/code.gitea.io/gitea/modules/web/route.go:103 +0x137 net/http.HandlerFunc.ServeHTTP(0xc0078427c0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 code.gitea.io/gitea/modules/web.Middle.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/code.gitea.io/gitea/modules/web/route.go:103 +0x137 net/http.HandlerFunc.ServeHTTP(0xc0078427e0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 code.gitea.io/gitea/modules/web.Middle.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/code.gitea.io/gitea/modules/web/route.go:103 +0x137 net/http.HandlerFunc.ServeHTTP(0xc007842800, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 github.com/go-chi/chi/middleware.GetHead.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/middleware/get_head.go:37 +0x182 net/http.HandlerFunc.ServeHTTP(0xc003c41248, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4700) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 code.gitea.io/gitea/modules/context.Contexter.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/code.gitea.io/gitea/modules/context/context.go:751 +0x1dca net/http.HandlerFunc.ServeHTTP(0xc0078474a0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 github.com/go-chi/chi.(*Mux).ServeHTTP(0xc007844d80, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:70 +0x5ab github.com/go-chi/chi.(*Mux).Mount.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:311 +0x17c net/http.HandlerFunc.ServeHTTP(0xc0078dfd40, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 github.com/go-chi/chi.(*Mux).routeHTTP(0xc004728f00, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:436 +0x28b net/http.HandlerFunc.ServeHTTP(0xc005c8db90, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 code.gitea.io/gitea/routers/routes.Recovery.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/code.gitea.io/gitea/routers/routes/base.go:211 +0x91 net/http.HandlerFunc.ServeHTTP(0xc005ca92c0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4600) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 gitea.com/go-chi/session.Sessioner.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/code.gitea.io/gitea/vendor/gitea.com/go-chi/session/session.go:256 +0x24f net/http.HandlerFunc.ServeHTTP(0xc005ca92e0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 code.gitea.io/gitea/modules/public.AssetsHandler.func1.1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/code.gitea.io/gitea/modules/public/public.go:42 +0x8f net/http.HandlerFunc.ServeHTTP(0xc005cd0ab0, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 github.com/go-chi/chi.(*Mux).ServeHTTP(0xc004728f00, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:70 +0x5ab github.com/go-chi/chi.(*Mux).Mount.func1(0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/code.gitea.io/gitea/vendor/github.com/go-chi/chi/mux.go:311 +0x17c net/http.HandlerFunc.ServeHTTP(0xc0078dfd60, 0x3f78d28, 0xc00e17ba80, 0xc00e1d4500) /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:2069 +0x44 created by net/http.(*Server).Serve /home/mural/src/golang.org/go1.16.3/src/net/http/server.go:3013 +0x39b ``` ![圖片](https://user-images.githubusercontent.com/2606021/122211444-50937c00-ced9-11eb-974f-9ad130bfb599.png)
Author
Owner

@typeless commented on GitHub (Jun 16, 2021):

Looking at 7e282be495/lexers/internal/api.go (L91-L98), I am afraid it's noticeably expensive to search for a lexer for every line of code.

See also f4d3bf7867/services/gitdiff/gitdiff.go (L551)

@typeless commented on GitHub (Jun 16, 2021): Looking at https://github.com/alecthomas/chroma/blob/7e282be4957c2cb4edeb4562f56d707427393192/lexers/internal/api.go#L91-L98, I am afraid it's noticeably expensive to search for a lexer for *every* line of code. See also https://github.com/go-gitea/gitea/blob/f4d3bf7867ac48d348f2c17637ca1229466c83bd/services/gitdiff/gitdiff.go#L551
Author
Owner

@typeless commented on GitHub (Jun 22, 2021):

Infinite scrolling pagination (https://www.digitalocean.com/community/tutorials/vuejs-implementing-infinite-scroll) might be a relatively simple way to address this if it doesn't require redesigning the UI.

@typeless commented on GitHub (Jun 22, 2021): Infinite scrolling pagination (https://www.digitalocean.com/community/tutorials/vuejs-implementing-infinite-scroll) might be a relatively simple way to address this if it doesn't require redesigning the UI.
Author
Owner

@zeripath commented on GitHub (Jun 24, 2021):

Looking at 7e282be495/lexers/internal/api.go (L91-L98), I am afraid it's noticeably expensive to search for a lexer for every line of code.

I guess that shows where we can seriously improve then...

The lexer detection should be run on the old file and run on the new file once and then reused.

@zeripath commented on GitHub (Jun 24, 2021): > Looking at https://github.com/alecthomas/chroma/blob/7e282be4957c2cb4edeb4562f56d707427393192/lexers/internal/api.go#L91-L98, I am afraid it's noticeably expensive to search for a lexer for _every_ line of code. I guess that shows where we can seriously improve then... The lexer detection should be run on the old file and run on the new file once and then reused.
Author
Owner

@typeless commented on GitHub (Jun 24, 2021):

@zeripath
#16180 helps to some extent, yet it's still suboptimal.
For the record, I have a PR that translates into 40MB of HTML and takes 10mins to generate (73 added files, btw). It seems to be stuck in html/template forever. Given the scenario, I think AJAX would probably make more difference in fixing this problem.

@typeless commented on GitHub (Jun 24, 2021): @zeripath #16180 helps to some extent, yet it's still suboptimal. For the record, I have a PR that translates into 40MB of HTML and takes 10mins to generate (73 added files, btw). It seems to be stuck in `html/template` forever. Given the scenario, I think AJAX would probably make more difference in fixing this problem.
Author
Owner

@zeripath commented on GitHub (Jun 24, 2021):

Yeah

@zeripath commented on GitHub (Jun 24, 2021): Yeah
Author
Owner

@zeripath commented on GitHub (Jun 24, 2021):

Agh I just read that pr. We need to change it. I don't think we can use arccache - it should be twoqueue I think

@zeripath commented on GitHub (Jun 24, 2021): Agh I just read that pr. We need to change it. I don't think we can use arccache - it should be twoqueue I think
Author
Owner

@typeless commented on GitHub (Jun 24, 2021):

Agh I just read that pr. We need to change it. I don't think we can use arccache - it should be twoqueue I think

Can you elaborate on their differences in this use case?

@typeless commented on GitHub (Jun 24, 2021): >Agh I just read that pr. We need to change it. I don't think we can use arccache - it should be twoqueue I think Can you elaborate on their differences in this use case?
Author
Owner

@zeripath commented on GitHub (Jun 24, 2021):

the issue is ARCCache is patent encumbered and known to be patent encumbered. We can't/shouldn't use that until the ARCCache patents expire - which it's potentially not until 2024 although someone says it's 2022.

@zeripath commented on GitHub (Jun 24, 2021): the issue is ARCCache is patent encumbered and known to be patent encumbered. We can't/shouldn't use that until the ARCCache patents expire - which it's potentially not until 2024 although someone says it's 2022.
Author
Owner

@zeripath commented on GitHub (Jun 24, 2021):

We should use a TwoQueue as the documentation for that library suggests which is equivalent but without the patent problem.

@zeripath commented on GitHub (Jun 24, 2021): We should use a TwoQueue as the documentation for that library suggests which is equivalent but without the patent problem.
Author
Owner

@typeless commented on GitHub (Jun 24, 2021):

@zeripath I see. I'll submit a pr later.

@typeless commented on GitHub (Jun 24, 2021): @zeripath I see. I'll submit a pr later.
Author
Owner

@leeN commented on GitHub (Nov 15, 2021):

This (sadly) makes Gitea more or less unusable for managing forks of large projects. We have forked a large open source project with a very active upstream so merging in new versions will easily pull in 15k+ new commits and 50k changed files.

Even trying to create a pull request via the web view hangs forever, commenting on it is pretty much impossible too :/

Gitea Version: 1.15.6
OS: Linux
Storage: SSDs (Raid1)
DB: Postgres

@leeN commented on GitHub (Nov 15, 2021): This (sadly) makes Gitea more or less unusable for managing forks of large projects. We have forked a large open source project with a very active upstream so merging in new versions will easily pull in 15k+ new commits and 50k changed files. Even trying to create a pull request via the web view hangs forever, commenting on it is pretty much impossible too :/ Gitea Version: 1.15.6 OS: Linux Storage: SSDs (Raid1) DB: Postgres
Author
Owner

@lunny commented on GitHub (Nov 15, 2021):

This (sadly) makes Gitea more or less unusable for managing forks of large projects. We have forked a large open source project with a very active upstream so merging in new versions will easily pull in 15k+ new commits and 50k changed files.

Even trying to create a pull request via the web view hangs forever, commenting on it is pretty much impossible too :/

Gitea Version: 1.15.6 OS: Linux Storage: SSDs (Raid1) DB: Postgres

I'm interested in what's the open source project.

@lunny commented on GitHub (Nov 15, 2021): > This (sadly) makes Gitea more or less unusable for managing forks of large projects. We have forked a large open source project with a very active upstream so merging in new versions will easily pull in 15k+ new commits and 50k changed files. > > Even trying to create a pull request via the web view hangs forever, commenting on it is pretty much impossible too :/ > > Gitea Version: 1.15.6 OS: Linux Storage: SSDs (Raid1) DB: Postgres I'm interested in what's the open source project.
Author
Owner

@leeN commented on GitHub (Nov 15, 2021):

I'm interested in what's the open source project.

Firefox, I merged in all changes between version 80 and 84 into our fork and the pull request page loads forever.

@leeN commented on GitHub (Nov 15, 2021): > I'm interested in what's the open source project. [Firefox](https://github.com/mozilla/gecko-dev), I merged in all changes between version 80 and 84 into our fork and the pull request page loads forever.
Author
Owner

@leeN commented on GitHub (Nov 16, 2021):

As a point of reference, I opened it on the Github Upstream repo. This took like 1s to load compared with the infinite loading time with Gitea.

@leeN commented on GitHub (Nov 16, 2021): As a point of reference, I opened it on the [Github](https://github.com/SAP/project-foxhound/pull/7) Upstream repo. This took like 1s to load compared with the infinite loading time with Gitea.
Author
Owner

@lunny commented on GitHub (Nov 16, 2021):

Yeah, because github will hide the changes. If you cannot view the changes, the PR cannot be reviewed manually.

@lunny commented on GitHub (Nov 16, 2021): Yeah, because github will hide the changes. If you cannot view the changes, the PR cannot be reviewed manually.
Author
Owner

@leeN commented on GitHub (Nov 16, 2021):

Yeah, because github will hide the changes. If you cannot view the changes, the PR cannot be reviewed manually.

I completely agree that it is impossible to review change sets that large in the web UI. If the UI doesn't render at all however, commenting on the pull request becomes impossible too as the comment box is rendered after all commits have loaded. This makes giving feedback based on checking out the PR locally via Gitea kinda impossible :)

I'm well aware that this is an edge case, but the option to hide the commits/changes similar to Github, if the change set is too large, would be a super helpful addition to Gitea :)

@leeN commented on GitHub (Nov 16, 2021): > Yeah, because github will hide the changes. If you cannot view the changes, the PR cannot be reviewed manually. I completely agree that it is impossible to review change sets that large in the web UI. If the UI doesn't render at all however, commenting on the pull request becomes impossible too as the comment box is rendered after all commits have loaded. This makes giving feedback based on checking out the PR locally via Gitea kinda impossible :) I'm well aware that this is an edge case, but the option to hide the commits/changes similar to Github, if the change set is too large, would be a super helpful addition to Gitea :)
Author
Owner

@lunny commented on GitHub (Nov 17, 2021):

OKay. So we can add an option to hide the file changes in the web UI but allow to create the PR successfully.

@lunny commented on GitHub (Nov 17, 2021): OKay. So we can add an option to hide the file changes in the web UI but allow to create the PR successfully.
Author
Owner

@leeN commented on GitHub (Nov 17, 2021):

That would be fantastic! :)

@leeN commented on GitHub (Nov 17, 2021): That would be fantastic! :)
Author
Owner

@NicolasPA commented on GitHub (Dec 10, 2021):

Similarly to the idea of having a tree of files that can be clicked to show the diff for one file, it would also be very useful to be able to select only one or more commits of the PR, which would also reduce the amount of diff displayed. This is the "Changes from" menu in Github:
image

@NicolasPA commented on GitHub (Dec 10, 2021): Similarly to the idea of having a tree of files that can be clicked to show the diff for one file, it would also be very useful to be able to select only one or more commits of the PR, which would also reduce the amount of diff displayed. This is the "Changes from" menu in Github: ![image](https://user-images.githubusercontent.com/22459427/145589720-ce18f59a-5836-4bff-aae1-3ec14639549a.png)
Author
Owner

@zeripath commented on GitHub (Dec 15, 2021):

AHA!

I bet you have some broken git repositories! I've just discovered that git cat-file --batch and git cat-file --batch-check will both hang until stdin is closed if the underlying "repository" is not a git repository. This is an infuriatingly bad behaviour which means we'll need to run git rev-parse on repository "open" to prevent the problem.

@zeripath commented on GitHub (Dec 15, 2021): AHA! I bet you have some broken git repositories! I've just discovered that `git cat-file --batch` and `git cat-file --batch-check` will both hang until stdin is closed if the underlying "repository" is not a git repository. This is an infuriatingly bad behaviour which means we'll need to run `git rev-parse` on repository "open" to prevent the problem.
Author
Owner

@gempir commented on GitHub (Feb 22, 2023):

FYI for readers: These settings have the most impact on the performance of the files changed page.

DISABLE_DIFF_HIGHLIGHT
MAX_GIT_DIFF_LINES
MAX_GIT_DIFF_LINE_CHARACTERS
MAX_GIT_DIFF_FILES

play around with them and figure out what works for you. I still think Bitbucket Server always had a really great concept for loading diffs, since it only ever had a single file open and you could just click in the file picker to the next one.

Rarely did I want to scroll through multiple files, since when are files vertically aligned to each other, they are always in a file system not a vertical line.

Is there lexer problem still relevant? Does it still look into the lexer for each line? I might want to have a look into that if so.

@gempir commented on GitHub (Feb 22, 2023): FYI for readers: These settings have the most impact on the performance of the files changed page. ``` DISABLE_DIFF_HIGHLIGHT MAX_GIT_DIFF_LINES MAX_GIT_DIFF_LINE_CHARACTERS MAX_GIT_DIFF_FILES ``` play around with them and figure out what works for you. I still think Bitbucket Server always had a really great concept for loading diffs, since it only ever had a single file open and you could just click in the file picker to the next one. Rarely did I want to scroll through multiple files, since when are files vertically aligned to each other, they are always in a file system not a vertical line. Is there lexer problem still relevant? Does it still look into the lexer for each line? I might want to have a look into that if so.
Author
Owner

@gempir commented on GitHub (Feb 22, 2023):

An alternative Idea could be building a Diff Viewer completely separate from the current one and implementing it purely in vuejs.

Syntax Highlighting has to be figured out then, but I think overall it could lead to a more customizable experience than the current server-client hybrid.

Although I really wish gitea could support vuejs SSR somehow, I'm not familiar enough with vuejs to judge if that's easy enough to implement.

@gempir commented on GitHub (Feb 22, 2023): An alternative Idea could be building a Diff Viewer completely separate from the current one and implementing it purely in vuejs. Syntax Highlighting has to be figured out then, but I think overall it could lead to a more customizable experience than the current server-client hybrid. Although I really wish gitea could support vuejs SSR somehow, I'm not familiar enough with vuejs to judge if that's easy enough to implement.
Author
Owner

@thigg commented on GitHub (Apr 18, 2023):

That would be a great hotfix to allow to show only one file at a time. I imagine it would be easy to implement and a very stable fallback mechanism until infinite scrolling etc stabilized. (reviewing large PRs got better recently but it is still very annoying)

Can someone outline what would have to be done for that?

@thigg commented on GitHub (Apr 18, 2023): That would be a great hotfix to allow to show only one file at a time. I imagine it would be easy to implement and a very stable fallback mechanism until infinite scrolling etc stabilized. (reviewing large PRs got better recently but it is still very annoying) Can someone outline what would have to be done for that?
Author
Owner

@lunny commented on GitHub (Apr 18, 2023):

I think #16829 has resolve this problem. You can set

[git]
MAX_GIT_DIFF_FILES = 

to limit the files loaded every time. And click Load More button on the bottom to load another page.

@lunny commented on GitHub (Apr 18, 2023): I think #16829 has resolve this problem. You can set ``` [git] MAX_GIT_DIFF_FILES = ``` to limit the files loaded every time. And click `Load More` button on the bottom to load another page.
Author
Owner

@lunny commented on GitHub (Jul 3, 2023):

Closed since loading files could be configured and there is a Load More button.

@lunny commented on GitHub (Jul 3, 2023): Closed since loading files could be configured and there is a `Load More` button.
Author
Owner

@thigg commented on GitHub (Jul 3, 2023):

I tried this with the current deployment on try: https://try.gitea.io/thigg/podqast/pulls/1/files
with 85k additions and 12k deletions and even though the site is loading in a matter of 10s of seconds I can not really type comments in there as there is a several seconds lag between typing and seeing the letter on the screen.

@lunny should this be a separate/new issue?

I agree that you should not have PRs this big... but if you get into the situation for some reason, it would be nice if at least gitea would not get in your way too.

@thigg commented on GitHub (Jul 3, 2023): I tried this with the current deployment on try: https://try.gitea.io/thigg/podqast/pulls/1/files with 85k additions and 12k deletions and even though the site is loading in a matter of 10s of seconds I can not really type comments in there as there is a several seconds lag between typing and seeing the letter on the screen. @lunny should this be a separate/new issue? I agree that you should not have PRs this big... but if you get into the situation for some reason, it would be nice if at least gitea would not get in your way too.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#6897