Skip to content

Conversation

@matklad
Copy link
Contributor

@matklad matklad commented Jan 14, 2020

Our syntax highlighting is accdentally quadratic. Current state of the PR fixes it in a pretty crude way, looks like for the proper fix we need to redo how source-analyzer works.

NB: don't be scared by diff stats, that's mostly a test-data file

@matklad matklad force-pushed the accidentally-quadratic branch from 411b575 to 99662f8 Compare January 14, 2020 16:30
@matklad matklad marked this pull request as ready for review January 14, 2020 16:57
@matklad
Copy link
Contributor Author

matklad commented Jan 14, 2020

@flodiebold curious what you think about this!

The problem here is that, when we go from InFile<AstNode> to hir::SomeID, we construct a DynMap, which stores SyntaxNode -> ID essentially. Construction the map is linear, and we did it for every child. (which goes back to your question about throwing away the map after we've checked a single entry).

Now, the obvious solution here is to add caching, however, it turns out not to be too straight-forward to implement. At least, not straight forward with salsa.

  • the first problem is that we want to store syntax trees, and I am afraid of caching syntax trees in salsa. It looks like with salsa garbage is generally collected in-between modifications (with the exception of LRU), and so we can accamulate a lot of stuff. I think the right approach here is to do caching on per-lsp request basis. IE, caching for highlighting of a single file
  • the second problem is that we want to store syntax trees, and SyntaxNodes in particular. And SyntaxNodes are not thread safe, so we can't put them in salsa (and yeas, Rust saved me couple of days of debugging, because I absolutely tried to do just that :-) ). We can use the usual trick of using a ptr instead of a node, but that leads to a more awkward API I think.

So, instead we introduce a SourceBinder, which holds a light-weight cache on top of the salsa. I think SourceBinder could potentially become a single entry point for IDE API. It is somewhat similar to exisrting SourceAnalyzer, but:

  • it can be reused freely in any context (while SourceAnalyzer is only valid in the context where it was created, and the precise definition of what that exactly means does not exist)
  • it also does what FromSource did before.

@flodiebold
Copy link
Member

Hmm, I have to think about this a bit, but this:

SourceAnalyzer is only valid in the context where it was created, and the precise definition of what that exactly means does not exist

is something that I noticed a lot when working on the assists. It made the API feel wrong, because it doesn't help you at all to use the correct SourceAnalyzer...


/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
/// original source files. It should not be used inside the HIR itself.
/// original source files. It should not be used pinside the HIR itself.

This comment was marked as resolved.

@kjeremy
Copy link
Contributor

kjeremy commented Jan 15, 2020

As an aside... are there operations we should be continuously benchmarking?

@matklad
Copy link
Contributor Author

matklad commented Jan 15, 2020

@kjeremy I don't think continuous benchmarking would be too valuable at the moment, as we haven't settled down on the overall architecture I think. That is, I expect that various random refactorings would affect benchmarks more than targeted optimization work.

We should have tests that something isn't exponentially slow though, like the one added in this PR, whose failure criteria is basically "the test suite never completes".

@matklad
Copy link
Contributor Author

matklad commented Jan 15, 2020

Also, it probably makes sense to fix things like #2821 (comment) or rust-lang/chalk#298 before starting the benchmarks.

@matklad matklad force-pushed the accidentally-quadratic branch 2 times, most recently from e7918f1 to b99d366 Compare January 15, 2020 14:03

#[test]
fn test_highlighting() {
fn te3st_highlighting() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo?

@matklad matklad force-pushed the accidentally-quadratic branch from b99d366 to aaef88d Compare January 15, 2020 15:53
Copy link
Member

@flodiebold flodiebold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me!

@matklad
Copy link
Contributor Author

matklad commented Jan 15, 2020

bors r+

bors bot added a commit that referenced this pull request Jan 15, 2020
2837: Accidentally quadratic r=matklad a=matklad

Our syntax highlighting is accdentally quadratic. Current state of the PR fixes it in a pretty crude way, looks like for the proper fix we need to redo how source-analyzer works. 

**NB:** don't be scared by diff stats, that's mostly a test-data file

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
@bors
Copy link
Contributor

bors bot commented Jan 15, 2020

Build succeeded

  • Rust (macos-latest)
  • Rust (ubuntu-latest)
  • TypeScript

@bors bors bot merged commit aaef88d into rust-lang:master Jan 15, 2020
@matklad matklad deleted the accidentally-quadratic branch January 15, 2020 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants