mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	Make profiling easier (#3634)
Add a `-profile` command line flag, and some documentation about how to collect and view profile data.
This commit is contained in:
		| @@ -154,31 +154,7 @@ If you want to trigger a debug session from VSCode, you can use the following sn | ||||
|  | ||||
| ## Profiling | ||||
|  | ||||
| If you want to investigate what's contributing to CPU usage you can add the following to the top of the `main()` function in `main.go` | ||||
|  | ||||
| ```go | ||||
| import "runtime/pprof" | ||||
|  | ||||
| func main() { | ||||
| 	f, err := os.Create("cpu.prof") | ||||
| 	if err != nil { | ||||
| 		log.Fatal("could not create CPU profile: ", err) | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 	if err := pprof.StartCPUProfile(f); err != nil { | ||||
| 		log.Fatal("could not start CPU profile: ", err) | ||||
| 	} | ||||
| 	defer pprof.StopCPUProfile() | ||||
| 	... | ||||
| ``` | ||||
|  | ||||
| Then run lazygit, and afterwards, from your terminal, run: | ||||
|  | ||||
| ```sh | ||||
| go tool pprof --web cpu.prof | ||||
| ``` | ||||
|  | ||||
| That should open an application which allows you to view the breakdown of CPU usage. | ||||
| If you want to investigate what's contributing to CPU or memory usage, see [this separate document](docs/dev/Profiling.md). | ||||
|  | ||||
| ## Testing | ||||
|  | ||||
|   | ||||
							
								
								
									
										69
									
								
								docs/dev/Profiling.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								docs/dev/Profiling.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| # Profiling Lazygit | ||||
|  | ||||
| If you want to investigate what's contributing to CPU or memory usage, start | ||||
| lazygit with the `-profile` command line flag. This tells it to start an | ||||
| integrated web server that listens for profiling requests. | ||||
|  | ||||
| ## Save profile data | ||||
|  | ||||
| ### CPU | ||||
|  | ||||
| While lazygit is running with the `-profile` flag, perform a CPU profile and | ||||
| save it to a file by running this command in another terminal window: | ||||
|  | ||||
| ```sh | ||||
| curl -o cpu.out http://127.0.0.1:6060/debug/pprof/profile | ||||
| ``` | ||||
|  | ||||
| By default, it profiles for 30 seconds. To change the duration, use | ||||
|  | ||||
| ```sh | ||||
| curl -o cpu.out 'http://127.0.0.1:6060/debug/pprof/profile?seconds=60' | ||||
| ``` | ||||
|  | ||||
| ### Memory | ||||
|  | ||||
| To save a heap profile (containing information about all memory allocated so | ||||
| far since startup), use | ||||
|  | ||||
| ```sh | ||||
| curl -o mem.out http://127.0.0.1:6060/debug/pprof/heap | ||||
| ``` | ||||
|  | ||||
| Sometimes it can be useful to get a delta log, i.e. to see how memory usage | ||||
| developed from one point in time to another. For that, use | ||||
|  | ||||
| ```sh | ||||
| curl -o mem.out 'http://127.0.0.1:6060/debug/pprof/heap?seconds=20' | ||||
| ``` | ||||
|  | ||||
| This will log the memory usage difference between now and 20 seconds later, so | ||||
| it gives you 20 seconds to perform the action in lazygit that you are interested | ||||
| in measuring. | ||||
|  | ||||
| ## View profile data | ||||
|  | ||||
| To display the profile data, you can either use speedscope.app, or the pprof | ||||
| tool that comes with go. I prefer the former because it has a nicer UI and is a | ||||
| little more powerful; however, I have seen cases where it wasn't able to load a | ||||
| profile for some reason, in which case it's good to have the pprof tool as a | ||||
| fallback. | ||||
|  | ||||
| ### Speedscope.app | ||||
|  | ||||
| Go to https://www.speedscope.app/ in your browser, and drag the saved profile | ||||
| onto the browser window. Refer to [the | ||||
| documentation](https://github.com/jlfwong/speedscope?tab=readme-ov-file#usage) | ||||
| for how to navigate the data. | ||||
|  | ||||
| ### Pprof tool | ||||
|  | ||||
| To view a profile that you saved as `cpu.out`, use | ||||
|  | ||||
| ```sh | ||||
| go tool pprof -http=:8080 cpu.out | ||||
| ``` | ||||
|  | ||||
| By default this shows the graph view, which I don't find very useful myself. | ||||
| Choose "Flame Graph" from the View menu to show a much more useful | ||||
| representation of the data. | ||||
| @@ -5,3 +5,4 @@ | ||||
| * [Integration Tests](../../pkg/integration/README.md) | ||||
| * [Demo Recordings](./Demo_Recordings.md) | ||||
| * [Find base commit for fixup design](Find_Base_Commit_For_Fixup_Design.md) | ||||
| * [Profiling](Profiling.md) | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	_ "net/http/pprof" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| @@ -30,6 +32,7 @@ type cliArgs struct { | ||||
| 	PrintVersionInfo   bool | ||||
| 	Debug              bool | ||||
| 	TailLogs           bool | ||||
| 	Profile            bool | ||||
| 	PrintDefaultConfig bool | ||||
| 	PrintConfigDir     bool | ||||
| 	UseConfigDir       string | ||||
| @@ -145,6 +148,14 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if cliArgs.Profile { | ||||
| 		go func() { | ||||
| 			if err := http.ListenAndServe("localhost:6060", nil); err != nil { | ||||
| 				log.Fatal(err) | ||||
| 			} | ||||
| 		}() | ||||
| 	} | ||||
|  | ||||
| 	parsedGitArg := parseGitArg(cliArgs.GitArg) | ||||
|  | ||||
| 	Run(appConfig, common, appTypes.NewStartArgs(cliArgs.FilterPath, parsedGitArg, integrationTest)) | ||||
| @@ -171,6 +182,9 @@ func parseCliArgsAndEnvVars() *cliArgs { | ||||
| 	tailLogs := false | ||||
| 	flaggy.Bool(&tailLogs, "l", "logs", "Tail lazygit logs (intended to be used when `lazygit --debug` is called in a separate terminal tab)") | ||||
|  | ||||
| 	profile := false | ||||
| 	flaggy.Bool(&profile, "", "profile", "Start the profiler and serve it on http port 6060. See CONTRIBUTING.md for more info.") | ||||
|  | ||||
| 	printDefaultConfig := false | ||||
| 	flaggy.Bool(&printDefaultConfig, "c", "config", "Print the default config") | ||||
|  | ||||
| @@ -202,6 +216,7 @@ func parseCliArgsAndEnvVars() *cliArgs { | ||||
| 		PrintVersionInfo:   printVersionInfo, | ||||
| 		Debug:              debug, | ||||
| 		TailLogs:           tailLogs, | ||||
| 		Profile:            profile, | ||||
| 		PrintDefaultConfig: printDefaultConfig, | ||||
| 		PrintConfigDir:     printConfigDir, | ||||
| 		UseConfigDir:       useConfigDir, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user