GitHub - 1jehuang/mermaid-rs-renderer: A fast native Rust Mermaid diagram renderer. No browser required. 500-1000x faster than mermaid-cli.

5 min read Original article ↗

mmdr

100-600x faster Mermaid rendering. Pure Rust. Zero browser dependencies.

Installation | Quick Start | Benchmarks | Examples

Performance

mmdr renders diagrams 100-600x faster than mermaid-cli by eliminating browser overhead.

Performance comparison

Diagram mmdr mermaid-cli Speedup
Flowchart 7.18 ms 2,252 ms 313x
Class Diagram 9.09 ms 2,317 ms 255x
State Diagram 9.32 ms 2,255 ms 242x
Sequence Diagram 6.19 ms 2,471 ms 399x

Tested on Intel Core Ultra 7 265V, Linux 6.18.2 | mermaid-cli 11.4.2 via Puppeteer/Chromium

Pipeline breakdown

Library Performance (no CLI overhead)

When used as a Rust library, mmdr is even faster with no process spawn overhead:

Library performance

Diagram Library Time
Flowchart 1.49 ms
Class Diagram 2.51 ms
State Diagram 2.04 ms
Sequence Diagram 0.07 ms

These are raw render times measured with Criterion, ideal for embedding in applications.

Extended Benchmarks

Performance on larger diagrams:

Diagram Nodes mmdr mermaid-cli Speedup
flowchart (small) 10 7.38 ms 2,082 ms 282x
flowchart (medium) 50 9.21 ms 2,287 ms 248x
flowchart (large) 200 26.32 ms 2,829 ms 108x

The speedup advantage decreases for very large diagrams as actual layout computation becomes more significant relative to browser startup overhead. Still, mmdr remains 100x+ faster even for 200-node diagrams.

Why mmdr?

The official mermaid-cli spawns a headless Chromium browser for every diagram, adding 2-3 seconds of startup overhead.

Use Case mermaid-cli mmdr
CI/CD pipeline with 50 diagrams ~2 minutes < 1 second
Real-time editor preview Unusable lag Instant
Batch doc generation Coffee break Blink of an eye

mmdr parses Mermaid syntax natively in Rust and renders directly to SVG. No browser. No Node.js. No Puppeteer.

Installation

# From source
cargo install --path .

# Homebrew (macOS/Linux)
brew tap 1jehuang/mmdr && brew install mmdr

# Scoop (Windows)
scoop bucket add mmdr https://github.com/1jehuang/scoop-mmdr && scoop install mmdr

# AUR (Arch)
yay -S mmdr-bin

Quick Start

# Pipe diagram to stdout
echo 'flowchart LR; A-->B-->C' | mmdr -e svg

# File to file
mmdr -i diagram.mmd -o output.svg -e svg
mmdr -i diagram.mmd -o output.png -e png

# Render all diagrams from a Markdown file
mmdr -i README.md -o ./diagrams/ -e svg

Diagram Types

mmdr supports 13 Mermaid diagram types:

Category Diagrams
Core Flowchart, Sequence, Class, State
Data ER Diagram, Pie Chart, XY Chart, Quadrant Chart
Planning Gantt, Timeline, Journey
Other Mindmap, Git Graph
Compare with mermaid-cli output
Type mmdr mermaid-cli
Flowchart
Class
State
Sequence
ER Diagram
Pie Chart
Gantt
Mindmap
Timeline
Journey
Git Graph
XY Chart
Quadrant

More Diagrams

Node Shapes
Shape Syntax
Rectangle [text]
Round (text)
Stadium ([text])
Diamond {text}
Hexagon {{text}}
Cylinder [(text)]
Circle ((text))
Double Circle (((text)))
Subroutine [[text]]
Parallelogram [/text/]
Trapezoid [/text\]
Asymmetric >text]
Edge Styles
Type Syntax Description
Arrow --> Standard arrow
Open --- No arrowhead
Dotted -.-> Dashed line with arrow
Thick ==> Bold arrow
Circle end --o Circle decoration
Cross end --x X decoration
Diamond end <--> Bidirectional
With label --|text|--> Labeled edge
Subgraphs
flowchart TB
    subgraph Frontend
        A[React App] --> B[API Client]
    end
    subgraph Backend
        C[Express Server] --> D[(PostgreSQL)]
    end
    B --> C

Subgraphs support:

  • Custom labels
  • Direction override (direction LR)
  • Nesting
  • Styling
Styling Directives
flowchart LR
    A[Start] --> B[End]

    classDef highlight fill:#f9f,stroke:#333
    class A highlight

    style B fill:#bbf,stroke:#333
    linkStyle 0 stroke:red,stroke-width:2px

Supported:

  • classDef - Define CSS classes
  • class - Apply classes to nodes
  • :::class - Inline class syntax
  • style - Direct node styling
  • linkStyle - Edge styling
  • %%{init}%% - Theme configuration

Features

Diagram types: flowchart / graph | sequenceDiagram | classDiagram | stateDiagram-v2 | erDiagram | pie | gantt | journey | timeline | mindmap | gitGraph | xychart-beta | quadrantChart

Node shapes: rectangle, round-rect, stadium, circle, double-circle, diamond, hexagon, cylinder, subroutine, trapezoid, parallelogram, asymmetric

Edges: solid, dotted, thick | Decorations: arrow, circle, cross, diamond | Labels

Styling: classDef, class, :::class, style, linkStyle, %%{init}%%

Layout: subgraphs with direction, nested subgraphs, automatic spacing

Configuration

mmdr -i diagram.mmd -o out.svg -c config.json
mmdr -i diagram.mmd -o out.svg --nodeSpacing 60 --rankSpacing 120
config.json example
{
  "themeVariables": {
    "primaryColor": "#F8FAFF",
    "primaryTextColor": "#1C2430",
    "primaryBorderColor": "#C7D2E5",
    "lineColor": "#7A8AA6",
    "secondaryColor": "#F0F4FF",
    "tertiaryColor": "#E8EEFF",
    "edgeLabelBackground": "#FFFFFF",
    "clusterBkg": "#F8FAFF",
    "clusterBorder": "#C7D2E5",
    "background": "#FFFFFF",
    "fontFamily": "Inter, system-ui, sans-serif",
    "fontSize": 13
  },
  "flowchart": {
    "nodeSpacing": 50,
    "rankSpacing": 50
  }
}

How It Works

Architecture comparison

mmdr implements the entire Mermaid pipeline natively:

.mmd → parser.rs → ir.rs → layout.rs → render.rs → SVG → resvg → PNG

mermaid-cli requires browser infrastructure:

.mmd → mermaid-js → layout → Browser DOM → Puppeteer → Chromium → Screenshot → PNG
mmdr mermaid-cli
Runtime Native binary Node.js + Chromium
Cold start ~3 ms ~2,000 ms
Memory ~15 MB ~300+ MB
Dependencies None Node.js, npm, Chromium

Library Usage

Use mmdr as a Rust library in your project:

[dependencies]
mermaid-rs-renderer = { git = "https://github.com/1jehuang/mermaid-rs-renderer" }
Minimal dependencies (for embedding)

For tools like Zola that only need SVG rendering, disable default features to avoid CLI and PNG dependencies:

[dependencies]
mermaid-rs-renderer = { git = "https://github.com/1jehuang/mermaid-rs-renderer", default-features = false }
Feature Default Description
cli Yes CLI binary and clap dependency
png Yes PNG output via resvg/usvg

This reduces dependencies from ~180 to ~80 crates.

use mermaid_rs_renderer::{render, render_with_options, RenderOptions};

// Simple one-liner
let svg = render("flowchart LR; A-->B-->C").unwrap();

// With custom options
let opts = RenderOptions::modern()
    .with_node_spacing(60.0)
    .with_rank_spacing(80.0);
let svg = render_with_options("flowchart TD; X-->Y", opts).unwrap();
Full pipeline control
use mermaid_rs_renderer::{
    parse_mermaid, compute_layout, render_svg,
    Theme, LayoutConfig,
};

let diagram = "flowchart LR; A-->B-->C";

// Stage 1: Parse
let parsed = parse_mermaid(diagram).unwrap();
println!("Parsed {} nodes", parsed.graph.nodes.len());

// Stage 2: Layout
let theme = Theme::modern();
let config = LayoutConfig::default();
let layout = compute_layout(&parsed.graph, &theme, &config);

// Stage 3: Render
let svg = render_svg(&layout, &theme, &config);
With timing information
use mermaid_rs_renderer::{render_with_timing, RenderOptions};

let result = render_with_timing(
    "flowchart LR; A-->B",
    RenderOptions::default()
).unwrap();

println!("Rendered in {:.2}ms", result.total_ms());
println!("  Parse:  {}us", result.parse_us);
println!("  Layout: {}us", result.layout_us);
println!("  Render: {}us", result.render_us);

Development

cargo test
cargo run -- -i docs/diagrams/architecture.mmd -o /tmp/out.svg -e svg

Benchmarks:

cargo bench --bench renderer              # Microbenchmarks
cargo build --release && python scripts/bench_compare.py  # vs mermaid-cli

License

MIT