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