# Performance Impact of Enabling Heredoc Scanning for Inline Scripts in dcg

> Discover the performance impact of enabling heredoc scanning for inline scripts in dcg. Learn about negligible latency, zero overhead, and sub-5ms processing for complex scripts without workflow stalls.

- Repository: [Jeff Emanuel/destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard)
- Tags: performance
- Published: 2026-07-13

---

**Enabling heredoc scanning in dcg adds negligible latency for most commands, with zero overhead for commands without heredocs and sub-5ms processing for complex inline scripts, while remaining fail-open to prevent workflow stalls.**

The `destructive_command_guard` (dcg) repository provides a security layer that inspects Bash commands before execution. When **heredoc scanning for inline scripts** is enabled, the evaluator extends its analysis pipeline to detect, extract, and analyze embedded scripts within heredoc blocks. This article examines the specific performance budgets, benchmark results, and architectural safeguards defined in the source code.

## Performance Tiers and Budgets

When heredoc scanning is active, dcg adds four specialized tiers to its evaluation hot-path. Each tier carries strict microsecond and millisecond budgets defined in [`src/perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/perf.rs) to ensure real-time command processing.

### Tier 3: Heredoc Trigger Detection

The first check uses a lightweight regex in `check_triggers` to determine if a command contains heredoc markers (`<<`). According to [`src/perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/perf.rs) lines 26-33, the budget for `HEREDOC_TRIGGER` is:

- **Target**: < 5 µs
- **Warning**: > 10 µs  
- **Panic**: > 100 µs

For commands without heredocs, this quick-reject test costs approximately 1 µs and exits the pipeline immediately.

### Tier 4: Heredoc Extraction

If the trigger fires, `extract_content` (defined in [`src/heredoc.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/heredoc.rs)) parses the `<<-EOF` blocks and enforces `ExtractionLimits`. The `HEREDOC_EXTRACT` budget in [`src/perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/perf.rs) lines 34-41 specifies:

- **Target**: < 200 µs
- **Warning**: > 500 µs
- **Panic**: > 2 ms

Benchmark measurements show a medium heredoc of approximately 50 lines consumes roughly 150 µs, while a large 500-line heredoc processes in approximately 1.2 ms—well within the panic threshold.

### Tier 5: Language Detection

The `ScriptLanguage::detect` function examines shebang lines and language-specific patterns to classify the extracted script. As defined in [`src/perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/perf.rs) lines 46-53, `LANGUAGE_DETECT` budgets are:

- **Target**: < 20 µs
- **Warning**: > 50 µs
- **Panic**: > 200 µs

Typical detection completes in under 10 µs for scripts with clear identifiers.

### Tier 6: Full Pipeline Execution

When a heredoc is present, `evaluate_command_with_pack_order` executes the complete pipeline. The `FULL_HEREDOC_PIPELINE` budget in [`src/perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/perf.rs) lines 60-67 sets aggressive limits:

- **Target**: < 5 ms
- **Warning**: > 15 ms
- **Panic**: > 20 ms

Even with large embedded scripts, the benchmark `bench_full_pipeline` demonstrates total processing times of 3-4 ms on modern hardware.

## Real-World Benchmark Results

The benchmark suite in [`benches/heredoc_perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/benches/heredoc_perf.rs) validates these budgets against representative workloads:

| Fixture | Size | Measured Time | Budget Status |
|---------|------|---------------|---------------|
| `simple_heredoc` (~3 lines) | Tiny | ~30 µs | ✅ Within target |
| `medium_heredoc` (~50 lines) | Moderate | ~150 µs | ✅ Below 200 µs warning |
| `large_heredoc` (~500 lines) | Heavy | ~1.2 ms | ✅ Below 2 ms panic |
| `full_pipeline` (complete evaluation) | Varied | 3-4 ms total | ✅ Below 5 ms target |

These measurements confirm that **enabling heredoc scanning for inline scripts** introduces microsecond-scale overhead for small snippets and remains under 5 ms for complex, multi-hundred-line embedded scripts.

## Configuration and Control

Heredoc scanning is controlled via `HeredocConfig` in [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs). By default, `HeredocSettings::default` enables scanning, but you can disable it entirely to eliminate tiers 3-6 overhead.

### Enabling or Disabling Heredoc Scanning

Create or edit `~/.config/dcg/config.toml`:

```toml
[heredoc]
enabled = true          # default: scan for heredocs

timeout_ms = 200        # max extraction time

max_body_bytes = 64_000
max_body_lines = 500
max_heredocs = 3
languages = ["bash", "python"]   # limit detection scope

```

When `enabled = false`, dcg skips all heredoc-specific processing and follows the standard quick-reject path.

## Fail-Open Safety Mechanism

The implementation in [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs) uses a **fail-open** strategy to prevent user workflow stalls. If any tier exceeds its panic threshold—such as encountering a pathological 10 KB heredoc—dcg immediately allows the command to execute and logs a warning. This ensures that performance edge cases never block legitimate operations.

## Summary

- **Zero overhead** applies to commands without heredocs due to the sub-5 µs quick-reject test in `check_triggers`.
- **Microsecond to millisecond overhead** occurs only when heredocs are present, with extraction typically consuming 30 µs to 1.2 ms depending on script size.
- **Sub-5 ms total processing** is maintained for the complete heredoc pipeline, including language detection and security analysis.
- **Fail-open behavior** guarantees that budget violations never stall the user, allowing commands to proceed while logging performance warnings.
- Configuration via [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs) allows complete disabling of the feature or tuning of limits via `ExtractionLimits`.

## Frequently Asked Questions

### What happens if heredoc extraction exceeds the time budget?

If `extract_content` in [`src/heredoc.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/heredoc.rs) exceeds the 2 ms panic threshold defined in [`src/perf.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/perf.rs), dcg triggers its fail-open mechanism. The command is immediately approved without full heredoc analysis, and a warning is logged to indicate the budget violation.

### How do I completely disable heredoc scanning to minimize overhead?

Set `enabled = false` in the `[heredoc]` section of your [`config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/config.toml). According to [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs), this prevents the evaluator from invoking `check_triggers` and subsequent tiers, reducing the hot-path to the standard command evaluation only.

### Does heredoc scanning slow down simple commands without embedded scripts?

No. For commands lacking heredoc markers, the `HEREDOC_TRIGGER` regex test in [`src/heredoc.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/heredoc.rs) executes in approximately 1 µs and returns immediately. This falls well within the existing fast-path budget and produces no measurable impact on execution flow.

### What are the default limits for heredoc extraction?

The `ExtractionLimits` struct in [`src/heredoc.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/heredoc.rs) enforces boundaries on parsed content. By default, the system limits extraction to 500 lines, 64 KB of body text, and 3 heredocs per command. These constraints prevent memory exhaustion and ensure the 5 ms total pipeline target remains achievable even with complex inline scripts.