From 4bebc00df26ccd977e356c40f433144278f4983c Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin <35292584+Myriad-Dreamin@users.noreply.github.com> Date: Tue, 21 Jan 2025 08:52:45 +0800 Subject: [PATCH] feat: delete useless async snapshot (#1206) --- crates/tinymist/src/cmd.rs | 15 +----- crates/tinymist/src/main.rs | 13 +++-- crates/tinymist/src/resource/fonts.rs | 5 +- crates/tinymist/src/resource/symbols.rs | 7 ++- crates/tinymist/src/state/input.rs | 12 +++-- crates/tinymist/src/state/project.rs | 72 +++++-------------------- crates/tinymist/src/state/query.rs | 5 +- crates/tinymist/src/state/server.rs | 14 +++-- crates/tinymist/src/stats.rs | 6 +-- 9 files changed, 43 insertions(+), 106 deletions(-) diff --git a/crates/tinymist/src/cmd.rs b/crates/tinymist/src/cmd.rs index 7393182d3..6764d6aa7 100644 --- a/crates/tinymist/src/cmd.rs +++ b/crates/tinymist/src/cmd.rs @@ -352,8 +352,6 @@ impl ServerState { let snap = self.snapshot().map_err(z_internal_error)?; just_future(async move { - let snap = snap.receive().await.map_err(z_internal_error)?; - // Parse the package specification. If the user didn't specify the version, // we try to figure it out automatically by downloading the package index // or searching the disk. @@ -397,8 +395,6 @@ impl ServerState { let snap = self.snapshot().map_err(z_internal_error)?; just_future(async move { - let snap = snap.receive().await.map_err(z_internal_error)?; - // Parse the package specification. If the user didn't specify the version, // we try to figure it out automatically by downloading the package index // or searching the disk. @@ -466,7 +462,6 @@ impl ServerState { let user_action = self.user_action; just_future(async move { - let snap = snap.receive().await.map_err(z_internal_error)?; let display_entry = || format!("{entry:?}"); // todo: rootless file @@ -555,7 +550,6 @@ impl ServerState { pub fn resource_package_dirs(&mut self, _arguments: Vec) -> AnySchedulableResponse { let snap = self.snapshot().map_err(z_internal_error)?; just_future(async move { - let snap = snap.receive().await.map_err(z_internal_error)?; let paths = snap.world.registry.paths(); let paths = paths.iter().map(|p| p.as_ref()).collect::>(); serde_json::to_value(paths).map_err(|e| internal_error(e.to_string())) @@ -569,7 +563,6 @@ impl ServerState { ) -> AnySchedulableResponse { let snap = self.snapshot().map_err(z_internal_error)?; just_future(async move { - let snap = snap.receive().await.map_err(z_internal_error)?; let paths = snap.world.registry.local_path(); let paths = paths.as_deref().into_iter().collect::>(); serde_json::to_value(paths).map_err(|e| internal_error(e.to_string())) @@ -585,7 +578,6 @@ impl ServerState { let snap = self.snapshot().map_err(z_internal_error)?; just_future(async move { - let snap = snap.receive().await.map_err(z_internal_error)?; let packages = tinymist_query::package::list_package_by_namespace(&snap.world.registry, ns) .into_iter() @@ -601,12 +593,10 @@ impl ServerState { &mut self, mut arguments: Vec, ) -> AnySchedulableResponse { - let fut = self.query_snapshot().map_err(internal_error)?; + let snap = self.query_snapshot().map_err(internal_error)?; let info = get_arg!(arguments[1] as PackageInfo); just_future(async move { - let snap = fut.receive().await.map_err(z_internal_error)?; - let symbols = snap .run_analysis(|a| { tinymist_query::docs::package_module_docs(a, &info) @@ -661,10 +651,9 @@ impl ServerState { info: PackageInfo, f: impl FnOnce(&mut LocalContextGuard) -> LspResult + Send + Sync, ) -> LspResult>> { - let fut = self.query_snapshot().map_err(internal_error)?; + let snap = self.query_snapshot().map_err(internal_error)?; Ok(async move { - let snap = fut.receive().await.map_err(z_internal_error)?; let world = &snap.world; let entry: StrResult = Ok(()).and_then(|_| { diff --git a/crates/tinymist/src/main.rs b/crates/tinymist/src/main.rs index a0548ddcd..52fc9f026 100644 --- a/crates/tinymist/src/main.rs +++ b/crates/tinymist/src/main.rs @@ -257,8 +257,6 @@ pub fn trace_lsp_main(args: TraceLspArgs) -> Result<()> { let snap = state.snapshot().unwrap(); RUNTIMES.tokio_runtime.block_on(async { - let snap = snap.receive().await.unwrap(); - let w = snap.world.task(TaskInputs { entry: Some(entry), inputs: Some(inputs), @@ -305,13 +303,13 @@ pub fn query_main(cmds: QueryCommands) -> Result<()> { let snap = state.snapshot().unwrap(); let res = RUNTIMES.tokio_runtime.block_on(async move { - let w = snap.receive().await.map_err(internal_error)?; match cmds { QueryCommands::PackageDocs(args) => { let pkg = PackageSpec::from_str(&args.id).unwrap(); let path = args.path.map(PathBuf::from); - let path = path - .unwrap_or_else(|| w.world.registry.resolve(&pkg).unwrap().as_ref().into()); + let path = path.unwrap_or_else(|| { + snap.world.registry.resolve(&pkg).unwrap().as_ref().into() + }); let res = state .resource_package_docs_(PackageInfo { @@ -328,8 +326,9 @@ pub fn query_main(cmds: QueryCommands) -> Result<()> { QueryCommands::CheckPackage(args) => { let pkg = PackageSpec::from_str(&args.id).unwrap(); let path = args.path.map(PathBuf::from); - let path = path - .unwrap_or_else(|| w.world.registry.resolve(&pkg).unwrap().as_ref().into()); + let path = path.unwrap_or_else(|| { + snap.world.registry.resolve(&pkg).unwrap().as_ref().into() + }); state .check_package(PackageInfo { diff --git a/crates/tinymist/src/resource/fonts.rs b/crates/tinymist/src/resource/fonts.rs index 768376e97..413ca6fca 100644 --- a/crates/tinymist/src/resource/fonts.rs +++ b/crates/tinymist/src/resource/fonts.rs @@ -1,11 +1,11 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; +use tinymist_project::LspCompileSnapshot; use tinymist_std::debug_loc::DataSource; use typst::text::{FontStretch, FontStyle, FontWeight}; use super::prelude::*; -use crate::project::WorldSnapFut; use crate::world::font::FontResolver; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -43,8 +43,7 @@ struct FontResourceResult { impl ServerState { /// Get the all valid fonts - pub async fn get_font_resources(snap: WorldSnapFut) -> LspResult { - let snap = snap.receive().await.map_err(internal_error)?; + pub async fn get_font_resources(snap: LspCompileSnapshot) -> LspResult { // fonts let resolver = &snap.world.font_resolver; let font_book = resolver.font_book(); diff --git a/crates/tinymist/src/resource/symbols.rs b/crates/tinymist/src/resource/symbols.rs index 811c043bc..ba90a2264 100644 --- a/crates/tinymist/src/resource/symbols.rs +++ b/crates/tinymist/src/resource/symbols.rs @@ -3,10 +3,11 @@ use std::{collections::BTreeMap, path::Path, sync::Arc}; // use reflexo_typst::font::GlyphId; use reflexo_typst::{vector::font::GlyphId, TypstDocument, TypstFont}; use sync_lsp::LspResult; +use tinymist_project::LspCompileSnapshot; use typst::{syntax::VirtualPath, World}; use crate::world::{base::ShadowApi, EntryState, TaskInputs}; -use crate::{project::WorldSnapFut, z_internal_error}; +use crate::z_internal_error; use super::prelude::*; @@ -947,9 +948,7 @@ static CAT_MAP: Lazy> = Lazy::new(|| { impl ServerState { /// Get the all valid symbols - pub async fn get_symbol_resources(snap: WorldSnapFut) -> LspResult { - let snap = snap.receive().await.map_err(z_internal_error)?; - + pub async fn get_symbol_resources(snap: LspCompileSnapshot) -> LspResult { let mut symbols = ResourceSymbolMap::new(); use typst::symbols::{emoji, sym}; populate_scope(sym().scope(), "sym", SymCategory::Misc, &mut symbols); diff --git a/crates/tinymist/src/state/input.rs b/crates/tinymist/src/state/input.rs index b88935b60..72a01301e 100644 --- a/crates/tinymist/src/state/input.rs +++ b/crates/tinymist/src/state/input.rs @@ -9,7 +9,7 @@ use once_cell::sync::OnceCell; use reflexo_typst::Bytes; use serde_json::{Map, Value as JsonValue}; use sync_lsp::*; -use tinymist_project::ProjectResolutionKind; +use tinymist_project::{Interrupt, ProjectResolutionKind}; use tinymist_query::{to_typst_range, PositionEncoding}; use tinymist_std::error::prelude::*; use tinymist_std::ImmutPath; @@ -165,10 +165,12 @@ impl ServerState { info!("the entry file of TypstActor(primary) is changing to {next_entry:?}"); - self.project.change_task(TaskInputs { + let id = self.project.state.primary.id.clone(); + let task = TaskInputs { entry: Some(next_entry.clone()), ..Default::default() - }); + }; + self.project.interrupt(Interrupt::ChangeTask(id, task)); Ok(true) } @@ -287,8 +289,8 @@ impl ServerState { } fn update_source(&mut self, files: FileChangeSet) -> Result<()> { - self.project - .add_memory_changes(MemoryEvent::Update(files.clone())); + let intr = Interrupt::Memory(MemoryEvent::Update(files.clone())); + self.project.interrupt(intr); Ok(()) } diff --git a/crates/tinymist/src/state/project.rs b/crates/tinymist/src/state/project.rs index a1f30130a..dda7ab2c6 100644 --- a/crates/tinymist/src/state/project.rs +++ b/crates/tinymist/src/state/project.rs @@ -12,7 +12,7 @@ //! //! We use typst by creating a [`ProjectCompiler`] and //! running compiler with callbacking [`CompileHandlerImpl`] incrementally. An -//! additional [`LocalCompileHandler`] is also created to control the +//! additional [`ProjectState`] is also created to control the //! [`ProjectCompiler`]. //! //! The [`CompileHandlerImpl`] will push information to other actors. @@ -34,12 +34,11 @@ use tinymist_query::{ VersionedDocument, }; use tinymist_std::{bail, error::prelude::*}; -use tokio::sync::{mpsc, oneshot}; +use tokio::sync::mpsc; use typst::diag::SourceDiagnostic; use crate::actor::editor::{CompileStatus, DocVersion, EditorRequest, TinymistCompileStatusEnum}; use crate::stats::{CompilerQueryStats, QueryStatGuard}; -use crate::world::vfs::MemoryEvent; type EditorSender = mpsc::UnboundedSender; @@ -99,31 +98,23 @@ pub struct ProjectState { impl ProjectState { /// Snapshot the compiler thread for tasks - pub fn snapshot(&mut self) -> Result { - let (tx, rx) = oneshot::channel(); - let snap = self.state.snapshot(); - let _ = tx.send(snap); - - Ok(WorldSnapFut { rx }) + pub fn snapshot(&mut self) -> Result { + Ok(self.state.snapshot()) } /// Snapshot the compiler thread for language queries - pub fn query_snapshot(&mut self, q: Option<&CompilerQueryRequest>) -> Result { - let fut = self.snapshot()?; + pub fn query_snapshot(&mut self, q: Option<&CompilerQueryRequest>) -> Result { + let snap = self.snapshot()?; let analysis = self.analysis.clone(); let rev_lock = analysis.lock_revision(q); - Ok(QuerySnapFut { - fut, + Ok(LspQuerySnapshot { + snap, analysis, rev_lock, }) } - pub fn add_memory_changes(&mut self, event: MemoryEvent) { - self.state.process(Interrupt::Memory(event)); - } - pub fn interrupt(&mut self, intr: Interrupt) { if let Interrupt::Compiled(compiled) = &intr { let proj = self.state.projects().find(|p| p.id == compiled.id); @@ -136,11 +127,6 @@ impl ProjectState { self.state.process(intr); } - pub fn change_task(&mut self, task: TaskInputs) { - self.state - .process(Interrupt::ChangeTask(self.state.primary.id.clone(), task)); - } - pub(crate) fn stop(&mut self) { // todo: stop all compilations } @@ -355,49 +341,15 @@ impl CompileHandler for CompileHandlerImpl } } -pub struct QuerySnapWithStat { - pub fut: QuerySnapFut, - pub(crate) stat: QueryStatGuard, -} - -pub struct WorldSnapFut { - rx: oneshot::Receiver, -} - -impl WorldSnapFut { - /// wait for the snapshot to be ready - pub async fn receive(self) -> Result { - self.rx - .await - .map_err(map_string_err("failed to get snapshot")) - } -} - -pub struct QuerySnapFut { - fut: WorldSnapFut, - analysis: Arc, - rev_lock: AnalysisRevLock, -} - -impl QuerySnapFut { - /// wait for the snapshot to be ready - pub async fn receive(self) -> Result { - let snap = self.fut.receive().await?; - Ok(QuerySnap { - snap, - analysis: self.analysis, - rev_lock: self.rev_lock, - }) - } -} +pub type QuerySnapWithStat = (LspQuerySnapshot, QueryStatGuard); -pub struct QuerySnap { +pub struct LspQuerySnapshot { pub snap: LspCompileSnapshot, analysis: Arc, rev_lock: AnalysisRevLock, } -impl std::ops::Deref for QuerySnap { +impl std::ops::Deref for LspQuerySnapshot { type Target = LspCompileSnapshot; fn deref(&self) -> &Self::Target { @@ -405,7 +357,7 @@ impl std::ops::Deref for QuerySnap { } } -impl QuerySnap { +impl LspQuerySnapshot { pub fn task(mut self, inputs: TaskInputs) -> Self { self.snap = self.snap.task(inputs); self diff --git a/crates/tinymist/src/state/query.rs b/crates/tinymist/src/state/query.rs index 21845de7b..7d806d564 100644 --- a/crates/tinymist/src/state/query.rs +++ b/crates/tinymist/src/state/query.rs @@ -336,7 +336,7 @@ impl ServerState { type R = CompilerQueryResponse; assert!(query.fold_feature() != FoldRequestFeature::ContextFreeUnique); - let fut_stat = self.query_snapshot_with_stat(&query)?; + let (mut snap, stat) = self.query_snapshot_with_stat(&query)?; let input = query .associated_path() .map(|path| self.resolve_task_with_state(path.into())) @@ -349,14 +349,13 @@ impl ServerState { }); just_future(async move { - let mut snap = fut_stat.fut.receive().await?; // todo: whether it is safe to inherit success_doc with changed entry if !is_pinning { if let Some(input) = input { snap = snap.task(input); } } - fut_stat.stat.snap(); + stat.snap(); if matches!(query, Completion(..)) { // Prefetch the package index for completion. diff --git a/crates/tinymist/src/state/server.rs b/crates/tinymist/src/state/server.rs index b98651d2e..5bc283411 100644 --- a/crates/tinymist/src/state/server.rs +++ b/crates/tinymist/src/state/server.rs @@ -25,8 +25,8 @@ use typst::syntax::Source; use crate::actor::editor::{EditorActor, EditorRequest}; use crate::project::world::EntryState; use crate::project::{ - update_lock, watch_deps, CompileHandlerImpl, CompileServerOpts, LspInterrupt, ProjectCompiler, - ProjectPreviewState, ProjectState, QuerySnapFut, QuerySnapWithStat, WorldSnapFut, + update_lock, watch_deps, CompileHandlerImpl, CompileServerOpts, LspInterrupt, LspQuerySnapshot, + ProjectCompiler, ProjectPreviewState, ProjectState, QuerySnapWithStat, PROJECT_ROUTE_USER_ACTION_PRIORITY, }; use crate::route::ProjectRouteState; @@ -180,12 +180,12 @@ impl ServerState { } /// Snapshot the compiler thread for tasks - pub fn snapshot(&mut self) -> Result { + pub fn snapshot(&mut self) -> Result { self.project.snapshot() } /// Snapshot the compiler thread for language queries - pub fn query_snapshot(&mut self) -> Result { + pub fn query_snapshot(&mut self) -> Result { self.project.query_snapshot(None) } @@ -197,8 +197,8 @@ impl ServerState { let name: &'static str = q.into(); let path = q.associated_path(); let stat = self.project.stats.query_stat(path, name); - let fut = self.project.query_snapshot(Some(q))?; - Ok(QuerySnapWithStat { fut, stat }) + let snap = self.project.query_snapshot(Some(q))?; + Ok((snap, stat)) } /// Install handlers to the language server. @@ -326,7 +326,6 @@ impl ServerState { let snap = self.snapshot()?; just_future(async move { - let snap = snap.receive().await?; let w = &snap.world; let info = ServerInfoResponse { @@ -545,7 +544,6 @@ impl ServerState { let snap = self.snapshot()?; let task = self.project.export.factory.task(); just_future(async move { - let snap = snap.receive().await?; let snap = snap.task(TaskInputs { entry: Some(entry), ..Default::default() diff --git a/crates/tinymist/src/stats.rs b/crates/tinymist/src/stats.rs index 1504c2c94..37787f7bf 100644 --- a/crates/tinymist/src/stats.rs +++ b/crates/tinymist/src/stats.rs @@ -32,11 +32,11 @@ impl Default for QueryStatBucketData { /// Statistics about some query #[derive(Default, Clone)] -pub(crate) struct QueryStatBucket { - pub data: Arc>, +pub struct QueryStatBucket { + pub(crate) data: Arc>, } -pub(crate) struct QueryStatGuard { +pub struct QueryStatGuard { pub bucket: QueryStatBucket, pub since: std::time::SystemTime, pub snap_since: OnceLock,