|  | # Running gopls as a daemon | 
|  |  | 
|  | **Note: this feature is new. If you encounter bugs, please [file an | 
|  | issue](troubleshooting.md#file-an-issue).** | 
|  |  | 
|  | If you just want to try this out, skip ahead to the [quickstart](#quickstart). | 
|  |  | 
|  | ## Background: gopls execution modes | 
|  |  | 
|  | Gopls was originally implemented as an LSP sidecar: a process started by | 
|  | editors or editor plugins, and communicated with using jsonrpc 2.0 over | 
|  | stdin/stdout. By executing as a stateful process, gopls can maintain a | 
|  | significant amount of cache and can eagerly perform analysis on the source code | 
|  | being edited. | 
|  |  | 
|  | This execution mode does not work as well when there are many separate editor | 
|  | processes or when editor processes are short-lived, as is often the case for | 
|  | users of non-IDE editors such as Vim or Emacs. Having many processes means | 
|  | having many caches, consuming a significant amount of system resources. Using | 
|  | short-lived sessions means paying a start-up cost each time a session is | 
|  | created. | 
|  |  | 
|  | To support these types of workflows, a new mode of gopls execution is supported | 
|  | wherein a single, persistent, shared gopls "daemon" process is responsible for | 
|  | managing all gopls sessions. In this mode, editors still start a gopls sidecar, | 
|  | but this sidecar merely acts as a thin "forwarder", responsible for forwarding | 
|  | the LSP to the shared gopls instance and recording metrics, logs, and rpc | 
|  | traces. | 
|  |  | 
|  | ## Quickstart | 
|  |  | 
|  | To use a shared gopls instance you must either manage the daemon process | 
|  | yourself, or let the gopls forwarder processes start the shared daemon as | 
|  | needed. | 
|  |  | 
|  | ### Running with `-remote=auto` | 
|  |  | 
|  | Automatic management of the daemon is easiest, and can be done by passing the | 
|  | flag `-remote=auto` to the gopls process started by your editor. This will | 
|  | cause this process to auto-start the gopls daemon if needed, connect to it, and | 
|  | forward the LSP. For example, here is a reasonable gopls invocation, that sets | 
|  | some additional flags for easier [debugging](#debugging): | 
|  |  | 
|  | ```bash | 
|  | gopls -remote=auto -logfile=auto -debug=:0 -remote.debug=:0 -rpc.trace | 
|  | ``` | 
|  |  | 
|  | Note that the shared gopls process will automatically shut down after one | 
|  | minute with no connected clients. | 
|  |  | 
|  | ### Managing the daemon manually | 
|  |  | 
|  | To manage the gopls daemon process via external means rather than having the | 
|  | forwarders manage it, you must start a gopls daemon process with the | 
|  | `-listen=<addr>` flag, and then pass `-remote=<addr>` to the gopls processes | 
|  | started by your editor. | 
|  |  | 
|  | For example, to host the daemon on the TCP port `37374`, do: | 
|  |  | 
|  | ```bash | 
|  | gopls -listen=:37374 -logfile=auto -debug=:0 | 
|  | ``` | 
|  |  | 
|  | And then from the editor, run | 
|  |  | 
|  | ```bash | 
|  | gopls -remote=:37374 -logfile=auto -debug=:0 -rpc.trace | 
|  | ``` | 
|  |  | 
|  | If you are on a POSIX system, you can also use unix domain sockets by prefixing | 
|  | the flag values with `unix;`. For example: | 
|  |  | 
|  | ```bash | 
|  | gopls -listen="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0 | 
|  | ``` | 
|  |  | 
|  | And connect via: | 
|  |  | 
|  | ```bash | 
|  | gopls -remote="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0 -rpc.trace | 
|  | ``` | 
|  |  | 
|  | (Note that these flag values MUST be enclosed in quotes, because ';' is a | 
|  | special shell character. For this reason, this syntax is subject to change in | 
|  | the future.) | 
|  |  | 
|  | ## Debugging | 
|  |  | 
|  | Debugging a shared gopls session is more complicated than a singleton session, | 
|  | because there are now two gopls processes involved with handling the LSP. Here | 
|  | are some tips: | 
|  |  | 
|  | ### Finding logfiles and debug addresses | 
|  |  | 
|  | When running in daemon mode, you can use the `gopls inspect sessions` command | 
|  | to find the logfile and debug port for your gopls daemon instance (as well as | 
|  | for all its connected clients). By default, this inspects the default daemon | 
|  | (i.e. `-remote=auto`). To inspect a different daemon, use the `-remote` flag | 
|  | explicitly: `gopls -remote=localhost:12345 inspect sessions`. | 
|  |  | 
|  | This works whether or not you have enabled `-remote.debug`. | 
|  |  | 
|  | ### Traversing debug pages | 
|  |  | 
|  | When `-debug=:0` is passed to gopls, it runs a webserver that serves stateful | 
|  | debug pages (see [troubleshooting.md](troubleshooting.md)). You can find the | 
|  | actual port hosting these pages by either using the `gopls inspect sessions` | 
|  | command, or by checking the start of the logfile -- it will be one of the first | 
|  | log messages. For example, if using `-logfile=auto`, find the debug address by | 
|  | checking `head /tmp/gopls-<pid>.log`. | 
|  |  | 
|  | By default, the gopls daemon is not started with `-debug`. To enable it, set | 
|  | the `-remote.debug` flag on the forwarder instance, so that it invokes gopls | 
|  | with `-debug` when starting the daemon. | 
|  |  | 
|  | The debug pages of the forwarder process will have a link to the debug pages of | 
|  | the daemon server process. Correspondingly, the debug pages of the daemon | 
|  | process will have a link to each of its clients. | 
|  |  | 
|  | This can help you find metrics, traces, and log files for all of the various | 
|  | servers and clients. | 
|  |  | 
|  | ### Using logfiles | 
|  |  | 
|  | The gopls daemon is started with logging disabled by default. To customize | 
|  | this, pass `-remote.logfile` to the gopls forwarder. Using | 
|  | `-remote.logfile=auto`, the daemon will log to a default location (on posix | 
|  | systems: `/tmp/gopls-daemon-<pid>.log`). | 
|  |  | 
|  | The gopls daemon does not log session-scoped messages: those are instead | 
|  | reflected back to the forwarder so that they can be accessed by the editor. | 
|  | Daemon logs will only contain global messages, for example logs when sessions | 
|  | connect and disconnect. | 
|  |  | 
|  | It is recommended to start the forwarder gopls process with `-rpc.trace`, so | 
|  | that its logfile will contain rpc trace logs specific to the LSP session. | 
|  |  | 
|  | ## Using multiple shared gopls instances | 
|  |  | 
|  | There may be environments where it is desirable to have more than one shared | 
|  | gopls instance. If managing the daemon manually, this can be done by simply | 
|  | choosing different `-listen` addresses for each distinct daemon process. | 
|  |  | 
|  | On POSIX systems, there is also support for automatic management of distinct | 
|  | shared gopls processes: distinct daemons can be selected by passing | 
|  | `-remote="auto;<id>"`. Any gopls forwarder passing the same value for `<id>` | 
|  | will use the same shared daemon. | 
|  |  | 
|  | ## FAQ | 
|  |  | 
|  | **Q: Why am I not saving as much memory as I expected when using a shared gopls?** | 
|  |  | 
|  | A: As described in [implementation.md](design/implementation.md), gopls has a | 
|  | concept of view/session/cache. Each session and view map onto exactly one | 
|  | editor session (because they contain things like edited but unsaved buffers). | 
|  | The cache contains things that are independent of any editor session, and can | 
|  | therefore be shared. | 
|  |  | 
|  | When, for example, three editor session are sharing a single gopls process, | 
|  | they will share the cache but will each have their own session and view. The | 
|  | memory savings in this mode, when compared to three separate gopls processes, | 
|  | corresponds to the amount of cache overlap across sessions. | 
|  |  | 
|  | Because this hasn't mattered much in the past, it is likely that there is state | 
|  | that can be moved out of the session/view, and into the cache, thereby | 
|  | increasing the amount of memory savings in the shared mode. | 
|  |  | 
|  | **Q: How do I customize the daemon instance when using `-remote=auto`?** | 
|  |  | 
|  | The daemon may be customized using flags of the form `-remote.*` on the | 
|  | forwarder gopls. This causes the forwarder to invoke gopls with these settings | 
|  | when starting the daemon. As of writing, we expose the following configuration: | 
|  |  | 
|  | * `-remote.logfile`: the location of the daemon logfile | 
|  | * `-remote.debug`: the daemon's debug address | 
|  | * `-remote.listen.timeout`: the amount of time the daemon should wait for new | 
|  | connections while there are no current connections, before shutting down. | 
|  | Must be set to a valid `time.Duration` (e.g. `30s` or `5m`). If `0`, listen | 
|  | indefinitely. Default: `1m`. | 
|  |  | 
|  | Note that once the daemon is already running, setting these flags will not | 
|  | change its configuration. These flags only matter for the forwarder process | 
|  | that actually starts the daemon. |