feat: add command to profile the entire server (#1438)

* feat: declare and bind tinymist.profileServer command

* feat: editor bridge with the frontend

* feat: start and stop server profiling

* feat: add profile-server prototype (#1440)

* Add profile-server prototype

* fix: use branch

---------

Co-authored-by: Myriad-Dreamin <camiyoru@gmail.com>

* feat: make it good

* build: update cargo.lock

* dev: ls profile impl and hook

* test: update snapshot

---------

Co-authored-by: Derived Cat <hooyuser@outlook.com>
This commit is contained in:
Myriad-Dreamin 2025-05-09 15:29:24 +08:00 committed by GitHub
parent 890ecd93a5
commit d6d3766b6f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 858 additions and 298 deletions

View file

@ -38,6 +38,7 @@ pub struct CallInfo {
// todo: cache call
/// Analyzes a function call.
#[typst_macros::time(span = node.span())]
pub fn analyze_call(
ctx: &mut LocalContext,
source: Source,

View file

@ -50,6 +50,7 @@ impl CompletionPair<'_, '_, '_> {
self.def_completions(defines, parens);
}
#[typst_macros::time]
pub fn scope_defs(&mut self) -> Option<Defines> {
let mut defines = Defines {
types: self.worker.ctx.type_check(&self.cursor.source),

View file

@ -81,6 +81,7 @@ impl HasNameRange for Decl {
// todo: field definition
/// Finds the definition of a symbol.
#[typst_macros::time(span = syntax.node().span())]
pub fn definition(
ctx: &Arc<SharedContext>,
source: &Source,

View file

@ -779,6 +779,7 @@ impl SharedContext {
}
/// Get the lint result of a source file.
#[typst_macros::time(span = source.root().span())]
pub(crate) fn lint(self: &Arc<Self>, source: &Source) -> LintInfo {
let ei = self.expr_stage(source);
let ti = self.type_check(source);
@ -1296,6 +1297,7 @@ fn ceil_char_boundary(text: &str, mut cursor: usize) -> usize {
cursor.min(text.len())
}
#[typst_macros::time]
#[comemo::memoize]
fn analyze_bib(
world: Tracked<dyn World + '_>,

View file

@ -8,6 +8,7 @@ use tinymist_world::package::PackageSpec;
use super::prelude::*;
/// Get link expressions from a source.
#[typst_macros::time(span = src.root().span())]
#[comemo::memoize]
pub fn get_link_exprs(src: &Source) -> Arc<LinkInfo> {
let root = LinkedNode::new(src.root());

View file

@ -13,6 +13,7 @@ use crate::ty::BuiltinTy;
/// With given type information, check the type of a literal expression again by
/// touching the possible related nodes.
#[typst_macros::time(span = node.span())]
pub(crate) fn post_type_check(
ctx: Arc<SharedContext>,
ti: &TypeInfo,

View file

@ -26,6 +26,7 @@ use crate::{
pub type SemanticTokens = Arc<Vec<SemanticToken>>;
/// Get the semantic tokens for a source.
#[typst_macros::time(span = source.root().span())]
pub(crate) fn get_semantic_tokens(ctx: &mut LocalContext, source: &Source) -> SemanticTokens {
let mut tokenizer = Tokenizer::new(
source.clone(),

View file

@ -30,6 +30,18 @@ pub enum SignatureTarget {
Convert(Func),
}
impl SignatureTarget {
/// Returns the span of the callee node.
pub fn span(&self) -> Span {
match self {
SignatureTarget::Def(_, def) => def.decl.span(),
SignatureTarget::SyntaxFast(_, span) | SignatureTarget::Syntax(_, span) => *span,
SignatureTarget::Runtime(func) | SignatureTarget::Convert(func) => func.span(),
}
}
}
#[typst_macros::time(span = callee_node.span())]
pub(crate) fn analyze_signature(
ctx: &Arc<SharedContext>,
callee_node: SignatureTarget,
@ -41,6 +53,7 @@ pub(crate) fn analyze_signature(
})
}
#[typst_macros::time(span = callee_node.span())]
fn analyze_type_signature(
ctx: &Arc<SharedContext>,
callee_node: &SignatureTarget,
@ -315,6 +328,7 @@ impl BoundChecker for AliasStackChecker<'_, '_> {
}
}
#[typst_macros::time(span = callee_node.span())]
fn analyze_dyn_signature(
ctx: &Arc<SharedContext>,
callee_node: &SignatureTarget,

View file

@ -29,6 +29,7 @@ pub struct TypeEnv {
}
/// Type checking at the source unit level.
#[typst_macros::time(span = ei.source.root().span())]
pub(crate) fn type_check(
ctx: Arc<SharedContext>,
ei: ExprInfo,
@ -228,14 +229,14 @@ impl TypeChecker<'_> {
&mut self,
sig: &Interned<SigTy>,
args: &Interned<SigTy>,
withs: Option<&Vec<Interned<SigTy>>>,
with: Option<&Vec<Interned<SigTy>>>,
) {
let call_desc = (sig.clone(), args.clone(), withs.cloned());
let call_desc = (sig.clone(), args.clone(), with.cloned());
if !self.call_cache.insert(call_desc) {
return;
}
for (arg_recv, arg_ins) in sig.matches(args, withs) {
for (arg_recv, arg_ins) in sig.matches(args, with) {
self.constrain(arg_ins, arg_recv);
}
}

View file

@ -12,6 +12,7 @@ static EMPTY_DOCSTRING: LazyLock<DocString> = LazyLock::new(DocString::default);
static EMPTY_VAR_DOC: LazyLock<VarDoc> = LazyLock::new(VarDoc::default);
impl TypeChecker<'_> {
#[typst_macros::time(span = expr.span())]
pub(crate) fn check_syntax(&mut self, expr: &Expr) -> Option<Ty> {
Some(match expr {
Expr::Block(exprs) => self.check_block(exprs),

View file

@ -28,6 +28,7 @@ use super::{compute_docstring, def::*, DocCommentMatcher, InterpretMode};
pub type ExprRoute = FxHashMap<TypstFileId, Option<Arc<LazyHash<LexicalScope>>>>;
#[typst_macros::time(span = source.root().span())]
pub(crate) fn expr_of(
ctx: Arc<SharedContext>,
source: Source,

View file

@ -12,6 +12,7 @@ pub struct IndexInfo {
pub(crate) identifiers: FxHashSet<Interned<str>>,
}
#[typst_macros::time(span = src.root().span())]
#[comemo::memoize]
pub fn get_index_info(src: &Source) -> Arc<IndexInfo> {
let root = src.root();

View file

@ -11,6 +11,7 @@ use typst_shim::utils::LazyHash;
use super::{is_mark, CommentGroupMatcher};
#[typst_macros::time(span = source.root().span())]
pub(crate) fn get_lexical_hierarchy(
source: &Source,
scope_kind: LexicalScopeKind,

View file

@ -18,6 +18,7 @@ pub struct ModuleDependency {
/// It will scan all the files in the context, using
/// [`LocalContext::source_files`], and find the dependencies and dependents
/// of each file.
#[typst_macros::time]
pub fn construct_module_dependencies(
ctx: &mut LocalContext,
) -> HashMap<TypstFileId, ModuleDependency> {