Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions rust/vm-provider/examples/regex_perf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use std::time::Instant;
use vm_provider::progress::DockerProgressParser;

fn main() {
let iterations = 10_000;
println!("Benchmarking DockerProgressParser instantiation ({} iterations)...", iterations);

let start = Instant::now();
for _ in 0..iterations {
let _parser = DockerProgressParser::new();
}
let duration = start.elapsed();

println!("Total time: {:?}", duration);
println!("Average time per instantiation: {:?}", duration / iterations);
}
25 changes: 16 additions & 9 deletions rust/vm-provider/src/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use regex::Regex;
use std::collections::HashMap;
use std::io::{self, Write};
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, OnceLock};
use std::time::Duration;
use tracing::info;
use vm_cli::msg;
Expand All @@ -21,12 +21,13 @@ pub trait ProgressParser: Send + Sync {

// --- Docker-specific Progress Parser --- //

static STEP_REGEX: OnceLock<Regex> = OnceLock::new();
static LAYER_PULL_REGEX: OnceLock<Regex> = OnceLock::new();

/// A progress parser specifically for `docker build` output.
pub struct DockerProgressParser {
mp: Arc<MultiProgress>,
main_bar: ProgressBar,
step_regex: Regex,
layer_pull_regex: Regex,
total_steps: u32,
current_step: u32,
layer_bars: HashMap<String, ProgressBar>,
Expand All @@ -48,10 +49,6 @@ impl DockerProgressParser {
Self {
mp,
main_bar,
step_regex: Regex::new(r"Step (\d+)/(\d+)")
.expect("Hardcoded Docker step regex pattern should always compile"),
layer_pull_regex: Regex::new(r"([a-f0-9]{12}): Pulling fs layer")
.expect("Hardcoded Docker layer pull regex pattern should always compile"),
total_steps: 0,
current_step: 0,
layer_bars: HashMap::new(),
Expand All @@ -67,7 +64,12 @@ impl Default for DockerProgressParser {

impl ProgressParser for DockerProgressParser {
fn parse_line(&mut self, line: &str) {
if let Some(caps) = self.step_regex.captures(line) {
let step_re = STEP_REGEX.get_or_init(|| {
Regex::new(r"Step (\d+)/(\d+)")
.expect("Hardcoded Docker step regex pattern should always compile")
});

if let Some(caps) = step_re.captures(line) {
let step: u32 = caps
.get(1)
.and_then(|m| m.as_str().parse().ok())
Expand All @@ -85,7 +87,12 @@ impl ProgressParser for DockerProgressParser {
self.main_bar.set_message(line.trim().to_string());
}

if let Some(caps) = self.layer_pull_regex.captures(line) {
let layer_re = LAYER_PULL_REGEX.get_or_init(|| {
Regex::new(r"([a-f0-9]{12}): Pulling fs layer")
.expect("Hardcoded Docker layer pull regex pattern should always compile")
});

if let Some(caps) = layer_re.captures(line) {
if let Some(layer_id_match) = caps.get(1) {
let layer_id = layer_id_match.as_str().to_string();
if !self.layer_bars.contains_key(&layer_id) {
Expand Down
Loading