Skip to content

perf: port entity extraction NER to Rust→WASM for faster memory write path (@stackbilt/wasm-core) #69

Description

@stackbilt-admin

Problem

extractEntities() in web/src/kernel/memory/graph.ts runs 5 separate matchAll regex passes on every memory consolidation ADD/UPDATE operation:

// graph.ts ~line 48
const CAPITALIZED_PHRASE = /\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)+)\b/g;
const TECH_TERMS = /\b(OAuth\s*2\.?1?|MCP|D1|KV|...)\b/g;
const VERSION_REFS = /\b(v\d+\.\d+(?:\.\d+)?|Phase\s+\d+)\b/gi;
const HYPHENATED_NAMES = /\b([a-z]+-[a-z]+(?:-[a-z0-9]+)?)\b/gi;

// Called on every ADD/UPDATE:
for (const match of fact.matchAll(CAPITALIZED_PHRASE)) { ... }
for (const match of fact.matchAll(TECH_TERMS)) { ... }
for (const match of fact.matchAll(VERSION_REFS)) { ... }
for (const match of fact.matchAll(HYPHENATED_NAMES)) { ... }
// + word scan against KNOWN_PROJECTS/KNOWN_TOOLS/KNOWN_PEOPLE Sets

JS regex engines reinterpret pattern strings on each call. With consolidation running every cron cycle and up to 3 ADD/UPDATE ops per run (plus extractNodes() calling this per node upsert), this adds up across the memory write pipeline.

Proposal

Port extractEntities() to Rust→WASM as part of @stackbilt/wasm-core (Phase 2):

  • Compile all 4 patterns once at WASM module init time using the Rust regex crate (which compiles to a DFA/NFA — significantly faster than repeated JS regex interpretation)
  • Known entity sets (KNOWN_PROJECTS, KNOWN_TOOLS, KNOWN_PEOPLE) become Rust HashSet<&str> — O(1) lookup, no JS object overhead
  • Single-pass extraction where possible (combine patterns into an alternation)
  • Expose: extract_entities(fact: string) -> string[]
// proposed usage
import { extractEntities } from '@stackbilt/wasm-core';
const entities = extractEntities(fact);  // Rust compiled regex, single pass

Why this fits WASM:

  • Pure string processing, no I/O
  • Rust regex crate compiles patterns to automata at init — subsequent matches are state-machine transitions, not interpretation
  • Known entity sets as static HashSet benefit from Rust's faster hashing (FxHashSet)
  • Called frequently on the memory write hot path

Scope

  • web/src/kernel/memory/graph.tsextractEntities() function
  • extractNodes() caller unchanged — just swaps the inner extraction call
  • No schema or API surface changes

Note: Lower priority than spreading activation (Phase 1). File for tracking. Not a code change request.

References

  • web/src/kernel/memory/graph.tsextractEntities(), extractNodes()
  • llm-providers#96 — Phase 0 (latency histogram)
  • aegis-oss#N — Phase 1 (spreading activation, filed in same session)
  • wiki: wasm-core-strategy-2026 (internal)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions