Architecture
Tinymist binary has multiple modes, and it may runs multiple actors in background. The actors could run as an async task, in a single thread, or in an isolated process.
The main process of tinymist runs the program as a language server, through stdin and stdout. A main process will fork:
- rendering actors to provide PDF export with watching.
- preview actors that give a document/outline preview over some typst source file.
- compiler actors to provide language APIs.
From the directory structure of crates/tinymist
, the main.rs
file parses the command line arguments and starts commands:
1
match args.command.unwrap_or_default() {
2
Commands::Query(query_cmds) => query_main(query_cmds),
3
Commands::Lsp(args) => lsp_main(args),
4
Commands::TraceLsp(args) => trace_lsp_main(args),
5
Commands::Preview(args) => tokio_runtime.block_on(preview_main(args)),
6
Commands::Probe => Ok(()),
7
}
1
match args.command.unwrap_or_default() {
2
Commands::Query(query_cmds) => query_main(query_cmds),
3
Commands::Lsp(args) => lsp_main(args),
4
Commands::TraceLsp(args) => trace_lsp_main(args),
5
Commands::Preview(args) => tokio_runtime.block_on(preview_main(args)),
6
Commands::Probe => Ok(()),
7
}
The query
subcommand contains the query commands, which are used to perform language queries via cli, which is convenient for debugging and profiling single query of the language server.
There are three servers in the server
directory:
lsp
provides the language server, initialized bylsp_main
inmain.rs
.trace
provides the trace server (profiling typst programs), initialized bytrace_lsp_main
inmain.rs
.preview
provides atypst-preview
compatible preview server, initialized bypreview_main
intool/preview.rs
.
The long-running servers are contributed by the ServerState
in the server.rs
file.
They will bootstrap actors in the actor
directory and start tasks in the task
directory.
They can construct and return resources in the resource
directory.
They may invoke tools in the tool
directory.
Debugging with input mirroring
You can record the input during running the editors with Tinymist. You can then replay the input to debug the language server.
1
# Record the input
2
tinymist lsp --mirror input.txt
3
# Replay the input
4
tinymist lsp --replay input.txt
1
# Record the input
2
tinymist lsp --mirror input.txt
3
# Replay the input
4
tinymist lsp --replay input.txt
Analyze memory usage with DHAT
You can build the program with dhat-heap
feature to collect memory usage with DHAT. The DHAT will instrument the allocator dynamically, so it will slow down the program significantly.
1
cargo build --release --bin tinymist --features dhat-heap
1
cargo build --release --bin tinymist --features dhat-heap
The instrumented program is nothing different from the normal program, so you can mine the specific memory usage with a lsp session (recorded with --mirror
) by replaying the input.
1
./target/release/tinymist lsp --replay input.txt
2
...
3
dhat: Total: 740,668,176 bytes in 1,646,987 blocks
4
dhat: At t-gmax: 264,604,009 bytes in 317,241 blocks
5
dhat: At t-end: 259,597,420 bytes in 313,588 blocks
6
dhat: The data has been saved to dhat-heap.json, and is viewable with dhat/dh_view.html
1
./target/release/tinymist lsp --replay input.txt
2
...
3
dhat: Total: 740,668,176 bytes in 1,646,987 blocks
4
dhat: At t-gmax: 264,604,009 bytes in 317,241 blocks
5
dhat: At t-end: 259,597,420 bytes in 313,588 blocks
6
dhat: The data has been saved to dhat-heap.json, and is viewable with dhat/dh_view.html
Once you have the dhat-heap.json
, you can visualize the memory usage with the DHAT viewer.
Contributing
See CONTRIBUTING.md.