Skip to content

Commit c2bb986

Browse files
Use a workspace level TokenMap and Engines (#7139)
## Description This PR moves `TokenMap` and `Engines` out of the `Session` type up to `ServerState` so a single instance of each can be shared across all workspace members. Up until now, each workspace member used a unique `Engines`. This meant the standard library and any other dependancies were unable to utilise the `QueryEngine` cache, leading to lots of duplicate entries. This was leading to inflated initialization times when opening a new workspace member and significantly increasing the RAM footprint of the language server. For example, opening each workspace member in the FUSD projects workspace would see RAM usage exceeding ~30.0 gig. Now we no longer exceed 2.0 gig of RAM. Future PR's will move the `BuildPlanCache` up to the `ServerState` level as well. part of #7111 & #6226 closes #5645 closes #5856 ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: kaya <[email protected]>
1 parent 512bbfc commit c2bb986

File tree

22 files changed

+393
-377
lines changed

22 files changed

+393
-377
lines changed

sway-lsp/benches/lsp_benchmarks/compile.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use codspeed_criterion_compat::{black_box, criterion_group, Criterion};
22
use forc_pkg::manifest::{GenericManifestFile, ManifestFile};
33
use lsp_types::Url;
4+
use parking_lot::RwLock;
45
use std::sync::Arc;
56
use sway_core::Engines;
67
use sway_lsp::core::session;
@@ -9,7 +10,7 @@ use tokio::runtime::Runtime;
910
const NUM_DID_CHANGE_ITERATIONS: usize = 10;
1011

1112
fn benchmarks(c: &mut Criterion) {
12-
let (uri, session, state) = Runtime::new()
13+
let (uri, session, state, _) = Runtime::new()
1314
.unwrap()
1415
.block_on(async { black_box(super::compile_test_project().await) });
1516

@@ -36,9 +37,11 @@ fn benchmarks(c: &mut Criterion) {
3637
});
3738

3839
c.bench_function("traverse", |b| {
39-
let engines = Engines::default();
40-
let results =
41-
black_box(session::compile(&build_plan, &engines, None, lsp_mode.as_ref()).unwrap());
40+
let engines_original = Arc::new(RwLock::new(Engines::default()));
41+
let engines_clone = engines_original.read().clone();
42+
let results = black_box(
43+
session::compile(&build_plan, &engines_clone, None, lsp_mode.as_ref()).unwrap(),
44+
);
4245
let session = Arc::new(session::Session::new());
4346
let member_path = sync.member_path(&uri).unwrap();
4447

@@ -47,8 +50,10 @@ fn benchmarks(c: &mut Criterion) {
4750
session::traverse(
4851
member_path.clone(),
4952
results.clone(),
50-
&engines,
53+
engines_original.clone(),
54+
&engines_clone,
5155
session.clone(),
56+
&state.token_map,
5257
lsp_mode.as_ref(),
5358
)
5459
.unwrap(),

sway-lsp/benches/lsp_benchmarks/mod.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,38 @@ pub mod token_map;
44

55
use lsp_types::Url;
66
use std::{path::PathBuf, sync::Arc};
7+
use sway_core::Engines;
78
use sway_lsp::{
9+
config::GarbageCollectionConfig,
810
core::session::{self, Session},
9-
server_state::ServerState,
11+
server_state::{CompilationContext, ServerState},
1012
};
1113

12-
pub async fn compile_test_project() -> (Url, Arc<Session>, ServerState) {
14+
pub async fn compile_test_project() -> (Url, Arc<Session>, ServerState, Engines) {
1315
// Load the test project
1416
let uri = Url::from_file_path(benchmark_dir().join("src/main.sw")).unwrap();
1517
let state = ServerState::default();
18+
let engines_clone = state.engines.read().clone();
1619
let session = Arc::new(Session::new());
1720
let sync = state.get_or_init_global_sync_workspace(&uri).await.unwrap();
1821
let temp_uri = sync.workspace_to_temp_url(&uri).unwrap();
1922

20-
let lsp_mode = Some(sway_core::LspConfig {
23+
state.documents.handle_open_file(&temp_uri).await;
24+
let ctx = CompilationContext {
25+
session: Some(session.clone()),
26+
sync: Some(sync.clone()),
27+
token_map: state.token_map.clone(),
28+
engines: state.engines.clone(),
2129
optimized_build: false,
2230
file_versions: Default::default(),
23-
});
31+
uri: Some(uri.clone()),
32+
version: None,
33+
gc_options: GarbageCollectionConfig::default(),
34+
};
2435

25-
state.documents.handle_open_file(&temp_uri).await;
2636
// Compile the project
27-
session::parse_project(
28-
&temp_uri,
29-
&session.engines.read(),
30-
None,
31-
lsp_mode,
32-
session.clone(),
33-
&sync,
34-
)
35-
.unwrap();
36-
(temp_uri, session, state)
37+
session::parse_project(&temp_uri, &engines_clone, None, &ctx).unwrap();
38+
(temp_uri, session, state, engines_clone)
3739
}
3840

3941
pub fn sway_workspace_dir() -> PathBuf {

sway-lsp/benches/lsp_benchmarks/requests.rs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,26 @@ use lsp_types::{
33
CompletionResponse, DocumentSymbolResponse, Position, Range, TextDocumentContentChangeEvent,
44
TextDocumentIdentifier,
55
};
6-
use sway_lsp::{
7-
capabilities, config::LspClient, lsp_ext::OnEnterParams, utils::keyword_docs::KeywordDocs,
8-
};
6+
use sway_lsp::{capabilities, lsp_ext::OnEnterParams};
97
use tokio::runtime::Runtime;
108

119
fn benchmarks(c: &mut Criterion) {
12-
let (uri, session, state) = Runtime::new()
10+
let (uri, session, state, engines) = Runtime::new()
1311
.unwrap()
1412
.block_on(async { black_box(super::compile_test_project().await) });
1513
let sync = state.sync_workspace.get().unwrap();
1614
let config = sway_lsp::config::Config::default();
17-
let keyword_docs = KeywordDocs::new();
1815
let position = Position::new(1717, 24);
1916
let range = Range::new(Position::new(1628, 0), Position::new(1728, 0));
2017

2118
c.bench_function("semantic_tokens", |b| {
22-
b.iter(|| capabilities::semantic_tokens::semantic_tokens_full(session.clone(), &uri))
19+
b.iter(|| capabilities::semantic_tokens::semantic_tokens_full(&state.token_map, &uri))
2320
});
2421

2522
c.bench_function("document_symbol", |b| {
2623
b.iter(|| {
2724
session
28-
.document_symbols(&uri)
25+
.document_symbols(&uri, &state.token_map, &engines)
2926
.map(DocumentSymbolResponse::Nested)
3027
})
3128
});
@@ -34,40 +31,44 @@ fn benchmarks(c: &mut Criterion) {
3431
let position = Position::new(1698, 28);
3532
b.iter(|| {
3633
session
37-
.completion_items(&uri, position, ".")
34+
.completion_items(&uri, position, ".", &state.token_map, &engines)
3835
.map(CompletionResponse::Array)
3936
})
4037
});
4138

4239
c.bench_function("hover", |b| {
4340
b.iter(|| {
44-
capabilities::hover::hover_data(
41+
capabilities::hover::hover_data(&state, &engines, session.clone(), &uri, position)
42+
})
43+
});
44+
45+
c.bench_function("highlight", |b| {
46+
b.iter(|| {
47+
capabilities::highlight::get_highlights(
4548
session.clone(),
46-
&keyword_docs,
49+
&engines,
50+
&state.token_map,
4751
&uri,
4852
position,
49-
LspClient::default(),
50-
sync,
5153
)
5254
})
5355
});
5456

55-
c.bench_function("highlight", |b| {
56-
b.iter(|| capabilities::highlight::get_highlights(session.clone(), &uri, position))
57-
});
58-
5957
c.bench_function("find_all_references", |b| {
60-
b.iter(|| session.token_references(&uri, position, sync))
58+
b.iter(|| session.token_references(&uri, position, &state.token_map, &engines, sync))
6159
});
6260

6361
c.bench_function("goto_definition", |b| {
64-
b.iter(|| session.token_definition_response(&uri, position, sync))
62+
b.iter(|| {
63+
session.token_definition_response(&uri, position, &engines, &state.token_map, sync)
64+
})
6565
});
6666

6767
c.bench_function("inlay_hints", |b| {
6868
b.iter(|| {
6969
capabilities::inlay_hints::inlay_hints(
70-
session.clone(),
70+
&engines,
71+
&state.token_map,
7172
&uri,
7273
&range,
7374
&config.inlay_hints,
@@ -76,13 +77,16 @@ fn benchmarks(c: &mut Criterion) {
7677
});
7778

7879
c.bench_function("prepare_rename", |b| {
79-
b.iter(|| capabilities::rename::prepare_rename(session.clone(), &uri, position, sync))
80+
b.iter(|| {
81+
capabilities::rename::prepare_rename(&engines, &state.token_map, &uri, position, sync)
82+
})
8083
});
8184

8285
c.bench_function("rename", |b| {
8386
b.iter(|| {
8487
capabilities::rename::rename(
85-
session.clone(),
88+
&engines,
89+
&state.token_map,
8690
"new_token_name".to_string(),
8791
&uri,
8892
position,
@@ -94,7 +98,15 @@ fn benchmarks(c: &mut Criterion) {
9498
c.bench_function("code_action", |b| {
9599
let range = Range::new(Position::new(4, 10), Position::new(4, 10));
96100
b.iter(|| {
97-
capabilities::code_actions::code_actions(session.clone(), &range, &uri, &uri, &vec![])
101+
capabilities::code_actions::code_actions(
102+
session.clone(),
103+
&engines,
104+
&state.token_map,
105+
&range,
106+
&uri,
107+
&uri,
108+
&vec![],
109+
)
98110
})
99111
});
100112

sway-lsp/benches/lsp_benchmarks/token_map.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,49 @@ use lsp_types::Position;
33
use tokio::runtime::Runtime;
44

55
fn benchmarks(c: &mut Criterion) {
6-
let (uri, session, state) = Runtime::new()
6+
let (uri, _, state, engines) = Runtime::new()
77
.unwrap()
88
.block_on(async { black_box(super::compile_test_project().await) });
99
let sync = state.sync_workspace.get().unwrap();
10-
let engines = session.engines.read();
1110
let position = Position::new(1716, 24);
11+
let path = uri.to_file_path().unwrap();
12+
let program_id = sway_lsp::core::session::program_id_from_path(&path, &engines).unwrap();
13+
c.bench_function("tokens_for_program", |b| {
14+
b.iter(|| {
15+
let _: Vec<_> = state.token_map.tokens_for_program(program_id).collect();
16+
})
17+
});
1218

1319
c.bench_function("tokens_for_file", |b| {
1420
b.iter(|| {
15-
let _: Vec<_> = session.token_map().tokens_for_file(&uri).collect();
21+
let _: Vec<_> = state.token_map.tokens_for_file(&uri).collect();
1622
})
1723
});
1824

1925
c.bench_function("idents_at_position", |b| {
2026
b.iter(|| {
21-
session
22-
.token_map()
23-
.idents_at_position(position, session.token_map().iter())
27+
state
28+
.token_map
29+
.idents_at_position(position, state.token_map.iter())
2430
})
2531
});
2632

2733
c.bench_function("tokens_at_position", |b| {
2834
b.iter(|| {
29-
session
30-
.token_map()
35+
state
36+
.token_map
3137
.tokens_at_position(&engines, &uri, position, None)
3238
})
3339
});
3440

3541
c.bench_function("token_at_position", |b| {
36-
b.iter(|| session.token_map().token_at_position(&uri, position))
42+
b.iter(|| state.token_map.token_at_position(&uri, position))
3743
});
3844

3945
c.bench_function("parent_decl_at_position", |b| {
4046
b.iter(|| {
41-
session
42-
.token_map()
47+
state
48+
.token_map
4349
.parent_decl_at_position(&engines, &uri, position)
4450
})
4551
});

sway-lsp/src/capabilities/code_actions/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,19 @@ pub(crate) struct CodeActionContext<'a> {
4444

4545
pub fn code_actions(
4646
session: Arc<Session>,
47+
engines: &Engines,
48+
token_map: &TokenMap,
4749
range: &Range,
4850
uri: &Url,
4951
temp_uri: &Url,
5052
diagnostics: &Vec<Diagnostic>,
5153
) -> Option<CodeActionResponse> {
52-
let t = session
53-
.token_map()
54-
.token_at_position(temp_uri, range.start)?;
54+
let t = token_map.token_at_position(temp_uri, range.start)?;
5555
let token = t.value();
5656

5757
let ctx = CodeActionContext {
58-
engines: &session.engines.read(),
59-
tokens: session.token_map(),
58+
engines,
59+
tokens: token_map,
6060
token,
6161
uri,
6262
temp_uri,
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
use crate::core::session::Session;
1+
use crate::core::{session::Session, token_map::TokenMap};
22
use lsp_types::{DocumentHighlight, Position, Url};
33
use std::sync::Arc;
4+
use sway_core::Engines;
45

56
pub fn get_highlights(
67
session: Arc<Session>,
8+
engines: &Engines,
9+
token_map: &TokenMap,
710
url: &Url,
811
position: Position,
912
) -> Option<Vec<DocumentHighlight>> {
1013
let _p = tracing::trace_span!("get_highlights").entered();
11-
session.token_ranges(url, position).map(|ranges| {
12-
ranges
13-
.into_iter()
14-
.map(|range| DocumentHighlight { range, kind: None })
15-
.collect()
16-
})
14+
session
15+
.token_ranges(engines, token_map, url, position)
16+
.map(|ranges| {
17+
ranges
18+
.into_iter()
19+
.map(|range| DocumentHighlight { range, kind: None })
20+
.collect()
21+
})
1722
}

0 commit comments

Comments
 (0)