Skip to main content
Glama
detection.rs7.19 kB
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; use terminal_mcp_core::{Dimensions, Position}; use terminal_mcp_detector::{ BorderDetector, ButtonDetector, CheckboxDetector, DetectionContext, DetectionPipeline, ElementDetector, InputDetector, MenuDetector, ProgressDetector, StatusBarDetector, TableDetector, }; use terminal_mcp_emulator::{Grid, Parser}; /// Create a grid with a bordered menu for benchmarking fn create_menu_parser(rows: u16, cols: u16) -> Parser { let grid = Grid::new(Dimensions::new(rows, cols)); let mut parser = Parser::new(grid); let menu_text = "\x1b[0m┌────────────────────┐\r\n│ View Status │\r\n│\x1b[7m> Start Service\x1b[0m │\r\n│ Stop Service │\r\n│ Quit │\r\n└────────────────────┘"; parser.process(menu_text.as_bytes()); parser } /// Create a grid with a table for benchmarking fn create_table_parser(rows: u16, cols: u16) -> Parser { let grid = Grid::new(Dimensions::new(rows, cols)); let mut parser = Parser::new(grid); let table_text = "\r\nID │ Name │ Status │ Time\r\n─────────────────────────────────\r\n1 │ Alice │ Active │ 12:30\r\n2 │ Bob │ Idle │ 12:35\r\n3 │ Charlie │ Active │ 12:40"; parser.process(table_text.as_bytes()); parser } /// Create a grid with various UI elements for full pipeline benchmark fn create_complex_parser(rows: u16, cols: u16) -> Parser { let grid = Grid::new(Dimensions::new(rows, cols)); let mut parser = Parser::new(grid); let complex_text = "─────────────────────────────────────────\r\n\r\nName: ____________________\r\n\r\n[ OK ] [Cancel]\r\n\r\n[X] Enable notifications\r\n\r\nProgress: ████████████████████░░░░░░░░░░\r\n\r\n\x1b[7mStatus: Ready | Time: 12:30 | Items: 5\x1b[0m"; parser.process(complex_text.as_bytes()); parser } fn bench_full_pipeline(c: &mut Criterion) { let mut group = c.benchmark_group("full_pipeline"); for size in [(24, 80), (40, 120), (60, 160)].iter() { let (rows, cols) = *size; let parser = create_complex_parser(rows, cols); let mut pipeline = DetectionPipeline::new(); // Add all detectors to pipeline pipeline.add_detector(std::sync::Arc::new(BorderDetector::new())); pipeline.add_detector(std::sync::Arc::new(StatusBarDetector::new())); pipeline.add_detector(std::sync::Arc::new(MenuDetector::new())); pipeline.add_detector(std::sync::Arc::new(TableDetector::new())); pipeline.add_detector(std::sync::Arc::new(InputDetector::new())); pipeline.add_detector(std::sync::Arc::new(ButtonDetector::new())); pipeline.add_detector(std::sync::Arc::new(CheckboxDetector::new())); pipeline.add_detector(std::sync::Arc::new(ProgressDetector::new())); let cursor = Position::new(0, 0); group.bench_with_input( BenchmarkId::from_parameter(format!("{rows}x{cols}")), &parser, |b, p| { b.iter(|| { let elements = pipeline.detect(black_box(p.grid()), black_box(cursor)); black_box(elements); }); }, ); } group.finish(); } fn bench_border_detector(c: &mut Criterion) { let parser = create_menu_parser(24, 80); let detector = BorderDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("border_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_menu_detector(c: &mut Criterion) { let parser = create_menu_parser(24, 80); let detector = MenuDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("menu_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_table_detector(c: &mut Criterion) { let parser = create_table_parser(24, 80); let detector = TableDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("table_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_input_detector(c: &mut Criterion) { let parser = create_complex_parser(24, 80); let detector = InputDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("input_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_button_detector(c: &mut Criterion) { let parser = create_complex_parser(24, 80); let detector = ButtonDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("button_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_checkbox_detector(c: &mut Criterion) { let parser = create_complex_parser(24, 80); let detector = CheckboxDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("checkbox_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_progress_detector(c: &mut Criterion) { let parser = create_complex_parser(24, 80); let detector = ProgressDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("progress_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } fn bench_status_bar_detector(c: &mut Criterion) { let parser = create_complex_parser(24, 80); let detector = StatusBarDetector::new(); let context = DetectionContext::new(Position::new(0, 0)); c.bench_function("status_bar_detector", |b| { b.iter(|| { let elements = detector.detect(black_box(parser.grid()), black_box(&context)); black_box(elements); }); }); } criterion_group!( benches, bench_full_pipeline, bench_border_detector, bench_menu_detector, bench_table_detector, bench_input_detector, bench_button_detector, bench_checkbox_detector, bench_progress_detector, bench_status_bar_detector ); criterion_main!(benches);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aybelatchane/mcp-server-terminal'

If you have feedback or need assistance with the MCP directory API, please join our Discord server