Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

vs. NDNts (TypeScript) and mw-nfd (Multi-worker NFD)

📝 Note: NDNts and mw-nfd serve different audiences than ndn-rs. NDNts targets browser and Node.js applications where JavaScript is the only option. mw-nfd targets existing NFD deployments that need higher throughput without a full rewrite. This comparison explains each project’s niche and where ndn-rs overlaps or differs.

This page compares ndn-rs with two further implementations: NDNts, a full NDN stack written in TypeScript that runs in browsers and Node.js, and mw-nfd, a modified NFD that adds a multi-threaded worker model to the reference C++ forwarder. They occupy distinct niches — browser applications and high-throughput C++ deployments, respectively — but both are common points of comparison when evaluating NDN implementations.

NDNts (TypeScript / Browser)

AspectNDNtsndn-rsRationale
Runtime environmentBrowser and Node.js. NDNts is the only NDN implementation that runs natively in a web browser via WebTransport and WebSocket faces. Bundle size is approximately 150 KB (gzip).Native binary and WASM. ndn-rs compiles to native code for servers and embedded targets, and to WASM for in-browser simulation (ndn-sim). The WASM build is not a production forwarder — it is used for research and testing.There is no substitute for NDNts when building a web application that needs to participate in an NDN network. ndn-rs does not compete here; it complements NDNts by acting as the router or producer that browser-based NDNts clients connect to.
Packet encodingTypeScript with BigInt TLV encoding. NDNts encodes TLV lengths as JavaScript BigInt values to handle >32-bit length fields correctly.bytes::Bytes zero-copy slicing. TLV is parsed directly over the wire buffer; no intermediate JavaScript objects are created per field.JavaScript’s JIT compiler can optimise hot encoding/decoding paths, but the overhead of object allocation per TLV field is unavoidable in a GC’d runtime. ndn-rs’s lazy decode via OnceLock and zero-copy Bytes slicing avoids per-field allocation entirely.
Face typesWebTransport, WebSocket, Unix socket (Node.js only). The face set is constrained by what browsers expose — no raw UDP multicast, no Ethernet, no shared memory.Full face set. UDP multicast, TCP unicast, Unix socket, shared-memory (ShmFace), in-process (InProcFace), and Ethernet (ndn-faces).Browser security policy prevents raw socket access, so NDNts’s face options are inherently limited. ndn-rs runs outside the browser sandbox and can use any OS networking primitive.
Concurrency modelSingle-threaded event loop. JavaScript is single-threaded; NDNts uses async/await over the event loop. True parallelism requires Web Workers with postMessage overhead for packet transfer.Multi-core async. ndn-rs uses Tokio’s multi-threaded runtime; pipeline stages and face I/O run on a shared thread pool without message-passing overhead between threads.JavaScript’s event loop model is excellent for I/O-bound tasks but cannot parallelize CPU-bound packet processing across cores. ndn-rs’s DashMap PIT and sharded locking are designed specifically to scale with core count.
Type safetyTypeScript (structural typing). NDNts is well-typed for a TypeScript library; type errors are caught at compile time. However, TypeScript types are erased at runtime, and any casts can silently bypass type checking.Rust (nominal typing with ownership). The compiler enforces not just type correctness but ownership and lifetime invariants. PacketContext cannot be used after it has been forwarded — this is a type error, not a runtime panic.Both projects prioritise correctness via type systems. Rust’s type system is strictly stronger: ownership eliminates a class of bugs (use-after-forward, data races) that TypeScript’s type system cannot express.
Signing and validationFull signing suite. NDNts supports SHA-256, ECDSA, RSA, and HMAC signing. It has the most complete browser-compatible signing story of any NDN implementation, using the Web Crypto API when available.Full signing suite via ndn-security. DigestSha256, EdDSA, ECDSA, BLAKE3, HMAC. Does not use Web Crypto (not in the browser).NDNts’s Web Crypto integration is its signing advantage — hardware key storage via the browser’s credential manager is accessible to NDNts but not to ndn-rs.
Ecosystem fitJavaScript/TypeScript ecosystem. NDNts is a set of npm packages; applications add it with npm install. Works with any JS build tool (Vite, webpack, esbuild).Rust ecosystem. ndn-rs is a set of Cargo crates. Works with Rust’s standard toolchain and cross-compilation targets.NDNts is the right choice whenever the application is already in JavaScript — a React SPA, an Electron app, a Next.js server. Rewriting in Rust to gain ndn-rs’s performance would rarely be justified for web applications.
SimulationNone built-in. Testing NDNts applications typically requires a real NFD or ndnd instance running locally.In-process simulation. ndn-sim provides SimFace and SimLink for topology simulation without any external process.The lack of a built-in simulation environment means NDNts integration tests depend on external infrastructure. ndn-rs integration tests are self-contained and run in CI without any setup.

mw-nfd (Multi-worker NFD, C++)

Aspectmw-nfdndn-rsRationale
ArchitectureModified NFD with a worker thread pool. mw-nfd adds multiple worker threads to NFD’s pipeline, each owning a subset of faces, while sharing global PIT and FIB data structures with reader-writer locks.Embeddable engine with DashMap PIT. ndn-rs is not a modification of an existing codebase; it was designed for concurrency from the start, with a sharded PIT and an async trait pipeline.mw-nfd’s multi-threading is bolted onto a single-threaded codebase. Shared data structures still require coarse reader-writer locks in many places. ndn-rs’s DashMap is sharded at a fine granularity, designed so that independent PIT entries can be inserted and looked up simultaneously.
DeploymentDrop-in for existing NFD deployments. mw-nfd is intended to replace nfd in existing setups; it speaks the same management protocol and uses the same configuration format.Independent binary (ndn-fwd) or embedded library. Compatible with NFD management protocol for monitoring tools; configuration is TOML-based rather than NFD-config.mw-nfd’s drop-in story is a genuine advantage for organisations already running NFD. Migrating to ndn-rs requires re-expressing configuration in TOML and updating any scripts that invoke NFD-specific internals. The NFD management protocol compatibility means monitoring tools (nfd-status) work without modification.
EmbeddabilityNot embeddable. mw-nfd is a daemon; applications connect over a Unix socket.Embeddable library. ndn-engine is a Rust crate that can be added as a dependency and run in-process.Same argument as vs. NFD: eliminating the IPC boundary removes a round-trip on every packet and allows the application and forwarder to share data structures directly.
Memory safetyC++ (unsafe). mw-nfd inherits NFD’s C++ codebase. The multi-threading changes introduce new shared mutable state that is difficult to audit for data races. ThreadSanitizer can catch races at runtime, but not exhaustively.Rust (memory-safe). The compiler rejects data races statically. Adding a new shared data structure forces the programmer to choose between Mutex, RwLock, or DashMap explicitly — the choice is visible in the type, not hidden in comments.Introducing shared mutable state into a previously single-threaded C++ codebase is one of the highest-risk refactors in systems programming. Rust’s ownership model makes this safe by construction: if it compiles, there are no data races.
PIT concurrencyGlobal reader-writer lock per worker, or per-worker PIT partitions (implementation varies by version). Contention can occur when multiple workers process packets for the same name prefix.DashMap: fine-grained sharding by name hash. Independent names in different shards never contend. Workers processing different name prefixes run in true parallel.Fine-grained sharding is more work to implement correctly but scales better under diverse traffic. A global or coarse lock limits throughput gains from adding more workers.
Strategy systemInherits NFD’s strategy system. Strategies are C++ classes; changing a strategy requires recompilation and daemon restart. mw-nfd adds no new strategy extensibility beyond NFD.Trait + WASM. Built-in strategies compile in; external strategies load as WASM modules at runtime without a restart.mw-nfd’s focus is throughput scaling, not strategy extensibility. ndn-rs adds runtime extensibility that mw-nfd does not attempt to address.
Forward compatibilityTied to NFD’s release cadence. mw-nfd is a fork; divergence from upstream NFD grows over time and merging upstream changes requires effort.Independent codebase. ndn-rs evolves on its own roadmap and tracks the NDN spec directly, not NFD’s implementation.Maintaining a fork of a large C++ project accumulates technical debt. ndn-rs does not carry this burden, but also lacks a decade of NFD’s production hardening.

Where NDNts and mw-nfd Have the Advantage

NDNts:

  • Browser-native. No other NDN implementation runs in a web browser. If your application is a web app, NDNts is the answer.
  • npm ecosystem. One npm install and it works with any JavaScript build pipeline. No Rust toolchain required.
  • Web Crypto integration. Hardware-backed key storage via browser credentials is accessible only to browser-native code.
  • Community. NDNts is actively maintained and has the widest adoption among JavaScript NDN developers.

mw-nfd:

  • Drop-in for NFD. Existing NFD deployments gain multi-core throughput with minimal configuration changes.
  • Spec authority. mw-nfd inherits NFD’s status as the reference implementation, so its forwarding behaviour is de facto correct by definition.
  • Production history. mw-nfd runs in real testbed deployments; ndn-rs’s multi-core forwarding is newer and less battle-tested at scale.

Complementary Deployment Pattern

A common pattern that uses all three projects together: NDNts runs in a browser application (consumer and producer), connecting over WebSocket to an ndn-fwd instance (ndn-rs) acting as an edge forwarder, which peers upstream with mw-nfd or NDN-DPDK nodes on the testbed backbone. Each implementation operates in the tier where it has the clearest advantage.