Skip to content

Commit 2f5a6b5

Browse files
committed
feat(ast-doc-core): enable hotpath feature for improved performance tracking
1 parent 750136f commit 2f5a6b5

9 files changed

Lines changed: 46 additions & 2 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ cucumber = "0.22.1"
2424
eyre = "0.6.12"
2525
git2 = "0.20.4"
2626
globset = "0.4.18"
27+
hotpath = { version = "0.5", default-features = false }
2728
ignore = "0.4.25"
2829
proptest = "1.11.0"
2930
rayon = "1.11.0"

bin/ast-doc/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@ categories.workspace = true
1111
description = "CLI for generating optimized llms.txt documentation from codebases"
1212
readme = "README.md"
1313

14+
[features]
15+
hotpath = ["ast-doc-core/hotpath", "dep:hotpath"]
16+
1417
[dependencies]
1518
ast-doc-core = { workspace = true }
1619
clap = { workspace = true, features = ["derive"] }
1720
eyre = { workspace = true }
21+
hotpath = { workspace = true, optional = true }
1822
tracing = { workspace = true }
1923
tracing-subscriber = { workspace = true }
2024

bin/ast-doc/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ pub fn build_config(args: &Args) -> ast_doc_core::AstDocConfig {
106106
}
107107

108108
fn main() -> Result<()> {
109+
#[cfg(feature = "hotpath")]
110+
let _guard = hotpath::GuardBuilder::new("main").build();
111+
109112
let args = Args::parse();
110113

111114
tracing_subscriber::fmt()

crates/ast-doc-core/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ all-languages = [
2020
"lang-c",
2121
]
2222
default = ["lang-rust"]
23+
hotpath = ["dep:hotpath"]
2324
lang-c = ["tree-sitter-c"]
2425
lang-go = ["tree-sitter-go"]
2526
lang-python = ["tree-sitter-python"]
@@ -30,6 +31,7 @@ lang-typescript = ["tree-sitter-typescript"]
3031
eyre = { workspace = true }
3132
git2 = { workspace = true }
3233
globset = { workspace = true }
34+
hotpath = { workspace = true, optional = true }
3335
ignore = { workspace = true }
3436
rayon = { workspace = true }
3537
serde_json = { workspace = true }
@@ -48,6 +50,7 @@ tree-sitter-typescript = { workspace = true, optional = true }
4850
workspace = true
4951

5052
[dev-dependencies]
53+
ctor = "0.2"
5154
cucumber = { workspace = true }
5255
proptest = { workspace = true }
5356
tempfile = { workspace = true }

crates/ast-doc-core/src/ingestion/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub struct IngestionResult {
5454
/// # Errors
5555
///
5656
/// Returns an error if directory walking or git operations fail.
57+
#[cfg_attr(feature = "hotpath", hotpath::measure)]
5758
pub fn run_ingestion(config: &AstDocConfig) -> Result<IngestionResult, AstDocError> {
5859
let root = config
5960
.path
@@ -123,8 +124,14 @@ pub fn run_ingestion(config: &AstDocConfig) -> Result<IngestionResult, AstDocErr
123124
}
124125

125126
/// Count tokens in a string using `tiktoken-rs`.
127+
///
128+
/// Uses a cached BPE instance to avoid repeated initialization.
126129
fn count_tokens(text: &str) -> usize {
127-
tiktoken_rs::cl100k_base().map_or(0, |bpe| bpe.encode_with_special_tokens(text).len())
130+
use std::sync::LazyLock;
131+
static BPE: LazyLock<Option<tiktoken_rs::CoreBPE>> =
132+
LazyLock::new(|| tiktoken_rs::cl100k_base().ok());
133+
134+
BPE.as_ref().map_or(0, |bpe| bpe.encode_with_special_tokens(text).len())
128135
}
129136

130137
/// Build a directory tree string from discovered file paths.

crates/ast-doc-core/src/lib.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub struct PipelineResult {
6666
/// # Errors
6767
///
6868
/// Returns an error if any pipeline stage fails.
69+
#[cfg_attr(feature = "hotpath", hotpath::measure)]
6970
pub fn run_pipeline(config: &AstDocConfig) -> eyre::Result<PipelineResult> {
7071
// Phase 1: Ingestion — file discovery, git metadata, directory tree
7172
let ingestion = ingestion::run_ingestion(config)?;
@@ -116,6 +117,22 @@ fn compute_base_overhead(ingestion: &IngestionResult) -> usize {
116117
}
117118

118119
/// Count tokens in a string using `tiktoken-rs`.
120+
///
121+
/// Uses a cached BPE instance to avoid repeated initialization.
119122
fn count_tokens(text: &str) -> usize {
120-
tiktoken_rs::cl100k_base().map_or(0, |bpe| bpe.encode_with_special_tokens(text).len())
123+
use std::sync::LazyLock;
124+
static BPE: LazyLock<Option<tiktoken_rs::CoreBPE>> =
125+
LazyLock::new(|| tiktoken_rs::cl100k_base().ok());
126+
127+
BPE.as_ref().map_or(0, |bpe| bpe.encode_with_special_tokens(text).len())
128+
}
129+
130+
/// Initialize hotpath guard for tests.
131+
///
132+
/// This is called automatically when running tests with the hotpath feature enabled.
133+
#[cfg(all(test, feature = "hotpath"))]
134+
#[ctor::ctor]
135+
fn init_hotpath_for_tests() {
136+
let _guard = hotpath::GuardBuilder::new("test").build();
137+
std::mem::forget(_guard);
121138
}

crates/ast-doc-core/src/renderer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{config::AstDocConfig, ingestion::IngestionResult, scheduler::Schedul
1212
/// # Errors
1313
///
1414
/// Returns an error if rendering fails.
15+
#[cfg_attr(feature = "hotpath", hotpath::measure)]
1516
pub fn render_llms_txt(
1617
scheduled: &ScheduleResult,
1718
ingestion: &IngestionResult,

crates/ast-doc-core/src/scheduler/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct ScheduleResult {
4848
///
4949
/// Returns `AstDocError::BudgetExceeded` if even minimum strategies
5050
/// exceed the token budget.
51+
#[cfg_attr(feature = "hotpath", hotpath::measure)]
5152
pub fn run_scheduler(
5253
parsed: &[ParsedFile],
5354
config: &AstDocConfig,

crates/ast-doc-core/tests/bdd.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
33
#![allow(clippy::print_stdout, clippy::print_stderr)]
44

5+
#[cfg(feature = "hotpath")]
6+
#[ctor::ctor]
7+
fn init_hotpath_for_bdd() {
8+
let _guard = hotpath::GuardBuilder::new("bdd_test").build();
9+
std::mem::forget(_guard);
10+
}
11+
512
use std::{fs, path::PathBuf};
613

714
use ast_doc_core::{

0 commit comments

Comments
 (0)