1# Running gopls as a daemon 2 3**Note: this feature is new. If you encounter bugs, please [file an 4issue](troubleshooting.md#file-an-issue).** 5 6If you just want to try this out, skip ahead to the [quickstart](#quickstart). 7 8## Background: gopls execution modes 9 10Gopls was originally implemented as an LSP sidecar: a process started by 11editors or editor plugins, and communicated with using jsonrpc 2.0 over 12stdin/stdout. By executing as a stateful process, gopls can maintain a 13significant amount of cache and can eagerly perform analysis on the source code 14being edited. 15 16This execution mode does not work as well when there are many separate editor 17processes or when editor processes are short-lived, as is often the case for 18users of non-IDE editors such as Vim or Emacs. Having many processes means 19having many caches, consuming a significant amount of system resources. Using 20short-lived sessions means paying a start-up cost each time a session is 21created. 22 23To support these types of workflows, a new mode of gopls execution is supported 24wherein a single, persistent, shared gopls "daemon" process is responsible for 25managing all gopls sessions. In this mode, editors still start a gopls sidecar, 26but this sidecar merely acts as a thin "forwarder", responsible for forwarding 27the LSP to the shared gopls instance and recording metrics, logs, and rpc 28traces. 29 30## Quickstart 31 32To use a shared gopls instance you must either manage the daemon process 33yourself, or let the gopls forwarder processes start the shared daemon as 34needed. 35 36### Running with `-remote=auto` 37 38Automatic management of the daemon is easiest, and can be done by passing the 39flag `-remote=auto` to the gopls process started by your editor. This will 40cause this process to auto-start the gopls daemon if needed, connect to it, and 41forward the LSP. For example, here is a reasonable gopls invocation, that sets 42some additional flags for easier [debugging](#debugging): 43 44```bash 45gopls -remote=auto -logfile=auto -debug=:0 -remote.debug=:0 -rpc.trace 46``` 47 48Note that the shared gopls process will automatically shut down after one 49minute with no connected clients. 50 51### Managing the daemon manually 52 53To manage the gopls daemon process via external means rather than having the 54forwarders manage it, you must start a gopls daemon process with the 55`-listen=<addr>` flag, and then pass `-remote=<addr>` to the gopls processes 56started by your editor. 57 58For example, to host the daemon on the TCP port `37374`, do: 59 60```bash 61gopls -listen=:37374 -logfile=auto -debug=:0 62``` 63 64And then from the editor, run 65 66```bash 67gopls -remote=:37374 -logfile=auto -debug=:0 -rpc.trace 68``` 69 70If you are on a POSIX system, you can also use unix domain sockets by prefixing 71the flag values with `unix;`. For example: 72 73```bash 74gopls -listen="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0 75``` 76 77And connect via: 78 79```bash 80gopls -remote="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0 -rpc.trace 81``` 82 83(Note that these flag values MUST be enclosed in quotes, because ';' is a 84special shell character. For this reason, this syntax is subject to change in 85the future.) 86 87## Debugging 88 89Debugging a shared gopls session is more complicated than a singleton session, 90because there are now two gopls processes involved with handling the LSP. Here 91are some tips: 92 93### Finding logfiles and debug addresses 94 95When running in daemon mode, you can use the `gopls inspect sessions` command 96to find the logfile and debug port for your gopls daemon instance (as well as 97for all its connected clients). By default, this inspects the default daemon 98(i.e. `-remote=auto`). To inspect a different daemon, use the `-remote` flag 99explicitly: `gopls -remote=localhost:12345 inspect sessions`. 100 101This works whether or not you have enabled `-remote.debug`. 102 103### Traversing debug pages 104 105When `-debug=:0` is passed to gopls, it runs a webserver that serves stateful 106debug pages (see [troubleshooting.md](troubleshooting.md)). You can find the 107actual port hosting these pages by either using the `gopls inspect sessions` 108command, or by checking the start of the logfile -- it will be one of the first 109log messages. For example, if using `-logfile=auto`, find the debug address by 110checking `head /tmp/gopls-<pid>.log`. 111 112By default, the gopls daemon is not started with `-debug`. To enable it, set 113the `-remote.debug` flag on the forwarder instance, so that it invokes gopls 114with `-debug` when starting the daemon. 115 116The debug pages of the forwarder process will have a link to the debug pages of 117the daemon server process. Correspondingly, the debug pages of the daemon 118process will have a link to each of its clients. 119 120This can help you find metrics, traces, and log files for all of the various 121servers and clients. 122 123### Using logfiles 124 125The gopls daemon is started with logging disabled by default. To customize 126this, pass `-remote.logfile` to the gopls forwarder. Using 127`-remote.logfile=auto`, the daemon will log to a default location (on posix 128systems: `/tmp/gopls-daemon-<pid>.log`). 129 130The gopls daemon does not log session-scoped messages: those are instead 131reflected back to the forwarder so that they can be accessed by the editor. 132Daemon logs will only contain global messages, for example logs when sessions 133connect and disconnect. 134 135It is recommended to start the forwarder gopls process with `-rpc.trace`, so 136that its logfile will contain rpc trace logs specific to the LSP session. 137 138## Using multiple shared gopls instances 139 140There may be environments where it is desirable to have more than one shared 141gopls instance. If managing the daemon manually, this can be done by simply 142choosing different `-listen` addresses for each distinct daemon process. 143 144On POSIX systems, there is also support for automatic management of distinct 145shared gopls processes: distinct daemons can be selected by passing 146`-remote="auto;<id>"`. Any gopls forwarder passing the same value for `<id>` 147will use the same shared daemon. 148 149## FAQ 150 151**Q: Why am I not saving as much memory as I expected when using a shared gopls?** 152 153A: As described in [implementation.md](implementation.md), gopls has a concept 154of view/session/cache. Each session and view map onto exactly one editor 155session (because they contain things like edited but unsaved buffers). The 156cache contains things that are independent of any editor session, and can 157therefore be shared. 158 159When, for example, three editor session are sharing a single gopls process, 160they will share the cache but will each have their own session and view. The 161memory savings in this mode, when compared to three separate gopls processes, 162corresponds to the amount of cache overlap across sessions. 163 164Because this hasn't mattered much in the past, it is likely that there is state 165that can be moved out of the session/view, and into the cache, thereby 166increasing the amount of memory savings in the shared mode. 167 168**Q: How do I customize the daemon instance when using `-remote=auto`?** 169 170The daemon may be customized using flags of the form `-remote.*` on the 171forwarder gopls. This causes the forwarder to invoke gopls with these settings 172when starting the daemon. As of writing, we expose the following configuration: 173 174* `-remote.logfile`: the location of the daemon logfile 175* `-remote.debug`: the daemon's debug address 176* `-remote.listen.timeout`: the amount of time the daemon should wait for new 177 connections while there are no current connections, before shutting down. If 178 `0`, listen indefinitely. 179 180Note that once the daemon is already running, setting these flags will not 181change its configuration. These flags only matter for the forwarder process 182that actually starts the daemon. 183