bench(interpreter): add fork_for_serving benchmark#147
Conversation
Track per-request interpreter fork cost with Criterion fixtures for both empty and closure-heavy templates, and surface the benchmark in CI. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Criterion benchmark target for Interpreter::fork_for_serving with CI bench job, replaces an old timing test with detailed closure-isolation tests, makes many path-related tests platform-portable, adds small Clippy suppressions, and adds a planning document. (50 words) ChangesCriterion Benchmark + Test Maintenance
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/interpreter/tests.rs`:
- Around line 804-815: The test uses a fixed temp filename
("forge_test_exists.txt") via the path variable which can collide across
parallel tests; change the test to generate a unique temp file per run (e.g.,
append a UUID/timestamp or use a temp-file helper) before calling
forge_string_literal_path(&path) so each invocation gets its own path; apply the
same change for the other test files referenced (the forge_copy_test* and
forge_csv_test.csv usages) so all tests create per-test unique names and avoid
global temp_dir() filename collisions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a8bb903d-121b-4c1c-b13f-dd0e723dcc4e
📒 Files selected for processing (5)
src/interpreter/tests.rssrc/package.rssrc/stdlib/fs.rssrc/stdlib/path_module.rssrc/vm/schedule_watch_tests.rs
✅ Files skipped from review due to trivial changes (1)
- src/stdlib/path_module.rs
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/interpreter/tests.rs`:
- Around line 25-27: forge_string_literal_path currently only escapes
backslashes which allows double quotes in temp paths to produce invalid Forge
string literals; update the function (forge_string_literal_path) to also escape
double-quote characters when producing the string literal (e.g., first replace
backslashes with \\ then replace " with \") so any embedded " in the path is
escaped before embedding into Forge source.
- Around line 29-35: The function unique_temp_path can still collide when
SystemTime has coarse resolution; add an in-process monotonic counter to the
path to guarantee uniqueness across rapid calls. Introduce a static AtomicU64
(e.g., STATIC_COUNTER) and fetch_add(1, Ordering::Relaxed) inside
unique_temp_path, then include that counter value in the formatted filename
alongside pid and nanos so each call always gets a unique PathBuf; keep the
existing nanos code as-is and only append the counter to the join format.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f9be59b6-24cf-4f4a-8314-380ff8e53bb3
📒 Files selected for processing (1)
src/interpreter/tests.rs
| fn forge_string_literal_path(path: &std::path::Path) -> String { | ||
| path.to_string_lossy().replace('\\', "\\\\") | ||
| } |
There was a problem hiding this comment.
Escape " as well when embedding paths into Forge string literals.
forge_string_literal_path currently escapes \ but not ". A temp path containing quotes will produce invalid Forge source.
Suggested fix
fn forge_string_literal_path(path: &std::path::Path) -> String {
- path.to_string_lossy().replace('\\', "\\\\")
+ path.to_string_lossy()
+ .replace('\\', "\\\\")
+ .replace('"', "\\\"")
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn forge_string_literal_path(path: &std::path::Path) -> String { | |
| path.to_string_lossy().replace('\\', "\\\\") | |
| } | |
| fn forge_string_literal_path(path: &std::path::Path) -> String { | |
| path.to_string_lossy() | |
| .replace('\\', "\\\\") | |
| .replace('"', "\\\"") | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/interpreter/tests.rs` around lines 25 - 27, forge_string_literal_path
currently only escapes backslashes which allows double quotes in temp paths to
produce invalid Forge string literals; update the function
(forge_string_literal_path) to also escape double-quote characters when
producing the string literal (e.g., first replace backslashes with \\ then
replace " with \") so any embedded " in the path is escaped before embedding
into Forge source.
| fn unique_temp_path(name: &str) -> std::path::PathBuf { | ||
| let nanos = std::time::SystemTime::now() | ||
| .duration_since(std::time::UNIX_EPOCH) | ||
| .map(|d| d.as_nanos()) | ||
| .unwrap_or(0); | ||
| std::env::temp_dir().join(format!("forge_{}_{}_{}", name, std::process::id(), nanos)) | ||
| } |
There was a problem hiding this comment.
unique_temp_path can still collide under coarse clock resolution.
Using only {pid}_{nanos} may duplicate when multiple calls land in the same timestamp bucket. Add a monotonic in-process counter to remove that flake vector.
Suggested fix
+use std::sync::atomic::{AtomicU64, Ordering};
+
+static TEMP_PATH_SEQ: AtomicU64 = AtomicU64::new(0);
+
fn unique_temp_path(name: &str) -> std::path::PathBuf {
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
- std::env::temp_dir().join(format!("forge_{}_{}_{}", name, std::process::id(), nanos))
+ let seq = TEMP_PATH_SEQ.fetch_add(1, Ordering::Relaxed);
+ std::env::temp_dir().join(format!(
+ "forge_{}_{}_{}_{}",
+ name,
+ std::process::id(),
+ nanos,
+ seq
+ ))
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn unique_temp_path(name: &str) -> std::path::PathBuf { | |
| let nanos = std::time::SystemTime::now() | |
| .duration_since(std::time::UNIX_EPOCH) | |
| .map(|d| d.as_nanos()) | |
| .unwrap_or(0); | |
| std::env::temp_dir().join(format!("forge_{}_{}_{}", name, std::process::id(), nanos)) | |
| } | |
| use std::sync::atomic::{AtomicU64, Ordering}; | |
| static TEMP_PATH_SEQ: AtomicU64 = AtomicU64::new(0); | |
| fn unique_temp_path(name: &str) -> std::path::PathBuf { | |
| let nanos = std::time::SystemTime::now() | |
| .duration_since(std::time::UNIX_EPOCH) | |
| .map(|d| d.as_nanos()) | |
| .unwrap_or(0); | |
| let seq = TEMP_PATH_SEQ.fetch_add(1, Ordering::Relaxed); | |
| std::env::temp_dir().join(format!( | |
| "forge_{}_{}_{}_{}", | |
| name, | |
| std::process::id(), | |
| nanos, | |
| seq | |
| )) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/interpreter/tests.rs` around lines 29 - 35, The function unique_temp_path
can still collide when SystemTime has coarse resolution; add an in-process
monotonic counter to the path to guarantee uniqueness across rapid calls.
Introduce a static AtomicU64 (e.g., STATIC_COUNTER) and fetch_add(1,
Ordering::Relaxed) inside unique_temp_path, then include that counter value in
the formatted filename alongside pid and nanos so each call always gets a unique
PathBuf; keep the existing nanos code as-is and only append the counter to the
join format.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Interpreter::fork_for_serving()with empty and closure-heavy fixtures..planning/.Test plan
Notes
cargo run -- testwithout--allow-runfails the shell builtin tests by design because shell execution is permission-gated.Made with Cursor
Summary by CodeRabbit
Tests
Chores
Style
Documentation