Open mark-christiaens opened 5 years ago
i assume we need to distinguish which resources are read and what is done. sequencing the reads has performance impacts, but how to detect what kind of operation does modify (loading resources, resolving references, installing adapters is impossible imho
the queue itself is single threaded, but the work is then offloaded i also cannot relate the line numbers to anything.
@szarnekow @kittaakos do you have any idea why it is done this way? is the assumption that the resource is already loaded?
@mark-christiaens what is the service you execute?
@cdietrich I connected VS code to our LSP server and was editing, navigating, hovering ... The reason why I think that I triggered the behavior is that our LSP server is quite slow: I suspect that many of the read and write requests take several seconds a piece. So the window for "raciness" is wide.
With regards to performance: correctness trumps speed. I too have no idea how to assure that the underlying resource set is not mutated: the notion of "read only" access to EMF does not exist. Maybe @kittaakos can clarify the reasoning?
The underlying assumption is that with our standard hooks the resources are all loaded during indexing or a write operation. @mark-christiaens do you run a language that does some late lazy loading of dependencies? We could maybe introduce some property per language that tells the LS if parallel read is ok. So if one participating language does on read loading it could veto this.
@svenefftinge
DisabledClusteringPolicy
) so that from time to time part of the resource set is removed. That might cause load operations during following read or write request that consult the resource set.No, it would not scale, but it performs nicely if it fits into memory. Assuming that for most usages the fast (and simple) default strategy works well, I'd like to allow languages to opt-out of the parallel read by configuration. I understand that this is not super safe but IIRC it makes quite a difference to allow parallel read. So'd vote for going with that unsafe compromise (we have it for two years now)
So what I am proposing is to change the manager to sequential read/write if a) one of the contributing language requires that b) the clustering policy is used.
The
org.eclipse.xtext.ide.server.concurrent.RequestManager
is executing read and write requests. AFAICT, the read operations are executed on theparallel
executor service. The write requests are executed by thequeue
executor. So, the net result is that read requests can occur in parallel. However, as we've seen multiple times in the past, theResource
s andResourceSet
s are not thread-safe. Even when only performing read operations, EMF will update parts of the model. I cannot identify a synchronization mechanism that makes this code thread-safe.I've seen
IllegalStateException
s being thrown like this:These seem to be caused by a race on adding a new
Resource
to theResourceSet
.I suspect that the "fix" is to make the execution of the read and write requests sequential (as is the case for the standard Xtext implementation).