diff options
Diffstat (limited to 'cli/bench/lsp.rs')
-rw-r--r-- | cli/bench/lsp.rs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/cli/bench/lsp.rs b/cli/bench/lsp.rs index 28d6d3759..a5994c653 100644 --- a/cli/bench/lsp.rs +++ b/cli/bench/lsp.rs @@ -9,11 +9,14 @@ use std::collections::HashMap; use std::path::Path; use std::time::Duration; use test_util::lsp::LspClientBuilder; +use test_util::PathRef; use tower_lsp::lsp_types as lsp; static FIXTURE_CODE_LENS_TS: &str = include_str!("testdata/code_lens.ts"); static FIXTURE_DB_TS: &str = include_str!("testdata/db.ts"); static FIXTURE_DB_MESSAGES: &[u8] = include_bytes!("testdata/db_messages.json"); +static FIXTURE_DECO_APPS: &[u8] = + include_bytes!("testdata/deco_apps_requests.json"); #[derive(Debug, Deserialize)] enum FixtureType { @@ -36,6 +39,107 @@ struct FixtureMessage { params: Value, } +/// replaces the root directory in the URIs of the requests +/// with the given root path +fn patch_uris<'a>( + reqs: impl IntoIterator<Item = &'a mut tower_lsp::jsonrpc::Request>, + root: &PathRef, +) { + for req in reqs { + let mut params = req.params().unwrap().clone(); + let new_req = if let Some(doc) = params.get_mut("textDocument") { + if let Some(uri_val) = doc.get_mut("uri") { + let uri = uri_val.as_str().unwrap(); + *uri_val = + Value::from(uri.replace( + "file:///", + &format!("file://{}/", root.to_string_lossy()), + )); + } + let builder = tower_lsp::jsonrpc::Request::build(req.method().to_owned()); + let builder = if let Some(id) = req.id() { + builder.id(id.clone()) + } else { + builder + }; + + Some(builder.params(params).finish()) + } else { + None + }; + + if let Some(new_req) = new_req { + *req = new_req; + } + } +} + +fn bench_deco_apps_edits(deno_exe: &Path) -> Duration { + let mut requests: Vec<tower_lsp::jsonrpc::Request> = + serde_json::from_slice(FIXTURE_DECO_APPS).unwrap(); + let apps = + test_util::root_path().join("cli/bench/testdata/lsp_benchdata/apps"); + + // it's a bit wasteful to do this for every run, but it's the easiest with the way things + // are currently structured + patch_uris(&mut requests, &apps); + + let mut client = LspClientBuilder::new() + .use_diagnostic_sync(false) + .set_root_dir(apps.clone()) + .deno_exe(deno_exe) + .build(); + client.initialize(|c| { + c.set_workspace_folders(vec![lsp_types::WorkspaceFolder { + uri: Url::from_file_path(&apps).unwrap(), + name: "apps".to_string(), + }]); + c.set_deno_enable(true); + c.set_unstable(true); + c.set_preload_limit(1000); + c.set_config(apps.join("deno.json").as_path().to_string_lossy()); + }); + + let start = std::time::Instant::now(); + + let mut reqs = 0; + for req in requests { + if req.id().is_none() { + client.write_notification(req.method(), req.params()); + } else { + reqs += 1; + client.write_jsonrpc(req.method(), req.params()); + } + } + for _ in 0..reqs { + let _ = client.read_latest_response(); + } + + let end = start.elapsed(); + + // part of the motivation of including this benchmark is to see how we perform + // with a fairly large number of documents in memory. + // make sure that's the case + let res = client.write_request( + "deno/virtualTextDocument", + json!({ + "textDocument": { + "uri": "deno:/status.md" + } + }), + ); + let re = lazy_regex::regex!(r"Documents in memory: (\d+)"); + let res = res.as_str().unwrap().to_string(); + assert!(res.starts_with("# Deno Language Server Status")); + let captures = re.captures(&res).unwrap(); + let count = captures.get(1).unwrap().as_str().parse::<usize>().unwrap(); + assert!(count > 1000, "count: {}", count); + + client.shutdown(); + + end +} + /// A benchmark that opens a 8000+ line TypeScript document, adds a function to /// the end of the document and does a level of hovering and gets quick fix /// code actions. @@ -309,6 +413,15 @@ pub fn benchmarks(deno_exe: &Path) -> HashMap<String, i64> { println!(" ({} runs, mean: {}ms)", times.len(), mean); exec_times.insert("code_lens".to_string(), mean); + println!(" - deco-cx/apps Multiple Edits + Navigation"); + let mut times = Vec::new(); + for _ in 0..5 { + times.push(bench_deco_apps_edits(deno_exe)); + } + let mean = + (times.iter().sum::<Duration>() / times.len() as u32).as_millis() as i64; + println!(" ({} runs, mean: {}ms)", times.len(), mean); + println!("<- End benchmarking lsp"); exec_times |