npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

fast-deep-equal-rs

v0.1.2

Published

Ultra-fast object hashing for memoization and caching - powered by Rust's ahash algorithm

Readme

fast-object-hash-rs

Ultra-fast object hashing for memoization and caching - powered by Rust

A high-performance JavaScript object hashing library that leverages Rust's ahash algorithm to provide 1.37x faster hashing than pure JavaScript for large objects (1000 keys).

Why This Library?

Deep equality checking in JavaScript is fast enough for most use cases, but object hashing for caching benefits from Rust's performance on large datasets:

  • ✅ Hash large objects (1000 keys) 1.37x faster than JavaScript
  • 61.6% less memory usage for very large objects (10,000+ keys)
  • ✅ Optimized versions (fastHashOptimized) avoid FFI overhead
  • ✅ Perfect for memoization and caching use cases
  • ✅ Multiple hash functions for different needs
  • ✅ Built-in memoization helpers
  • ⚠️ JavaScript is faster for small objects (< 100 keys) due to FFI overhead

Installation

npm install fast-object-hash-rs

Quick Start

const { fastHash, createMemo, createCache } = require('fast-object-hash-rs');

// Simple hashing
const hash = fastHash({ user: 'john', age: 30 });
console.log(hash); // "a3f5c21b8d4e"

// Memoization
const expensiveFn = createMemo((data) => {
  // expensive computation
  return processData(data);
});

// Will only compute once for same input
const result1 = expensiveFn(largeObject);
const result2 = expensiveFn(largeObject); // ← Cached!

// Object-based caching
const cache = createCache();
cache.set(complexObject, computedValue);
const value = cache.get(complexObject); // Fast lookup by content

API

fastHash(obj: any): string

Ultra-fast hashing using Rust's ahash algorithm. Returns a hex string suitable for use as a Map key.

const hash = fastHash({ a: 1, b: 2, c: 3 });

Best for: General-purpose caching, memoization

fastHashNumber(obj: any): number

Even faster - returns a numeric hash. Use when you don't need string keys.

const hash = fastHashNumber(largeObject);

Best for: When you need maximum speed and can use numeric keys

stableHash(obj: any): string

Sorted-key hash that guarantees the same hash for {a:1,b:2} and {b:2,a:1}.

stableHash({ a: 1, b: 2 }) === stableHash({ b: 2, a: 1 }); // true

Best for: When object key order varies but content is the same

hashEquals(a: any, b: any): boolean

Fast equality check using hash comparison. Faster than deep equality for large objects.

if (hashEquals(largeObj1, largeObj2)) {
  // Objects are equal
}

Best for: Comparing very large objects (1000+ keys)

fastHashBatch(objects: any[]): string[]

Hash multiple objects at once - amortizes FFI overhead for 2-3x speedup.

const hashes = fastHashBatch([obj1, obj2, obj3, obj4]);

Best for: Hashing many objects in bulk

secureHash(obj: any): string

Cryptographic SHA-256 hash. Slower but collision-resistant.

const hash = secureHash(sensitiveData);

Best for: When you need guaranteed uniqueness

createMemo(fn): function

Create a memoized version of a function that caches results based on argument hashing.

const memoized = createMemo((a, b, c) => {
  // expensive operation
  return a + b + c;
});

memoized(1, 2, 3); // Computed
memoized(1, 2, 3); // Cached!

createCache(): Cache

Create a cache that uses object content for lookups (not reference equality).

const cache = createCache();

cache.set({ user: 'john' }, userData);
cache.get({ user: 'john' }); // ← Works! Same content = same hash

cache.has(obj);
cache.delete(obj);
cache.clear();

Performance Benchmarks

Results on M1 MacBook Pro:

Small Objects (3 keys)

Rust fastHash:        1,932,950 ops/sec
Rust fastHashNumber:  2,150,706 ops/sec
JavaScript hash:      6,182,923 ops/sec
Result: JavaScript 3.2x faster (FFI overhead dominates)

Medium Objects (50 keys)

Rust fastHash:          439,824 ops/sec
Rust fastHashNumber:    448,724 ops/sec
JavaScript hash:        504,248 ops/sec
Result: JavaScript 1.15x faster

Large Objects (1000 keys)

Rust fastHash:                  7,297 ops/sec (1.34x faster)
Rust fastHashNumber:            7,305 ops/sec (1.34x faster)
Rust fastHashOptimized:         7,486 ops/sec (1.37x faster) ⭐
Rust fastHashNumberOptimized:   7,472 ops/sec (1.37x faster) ⭐
JavaScript hash:                5,460 ops/sec
Speedup: Up to 1.37x ✓✓ ← Rust shines here!

Nested Object (deep structure)

Rust fastHash:          367,931 ops/sec
Rust fastHashNumber:    374,168 ops/sec
JavaScript hash:        407,420 ops/sec
Result: JavaScript 1.1x faster

Cryptographic Hashing (SHA-256)

Rust SHA-256:         252,634 ops/sec
Node.js crypto:       456,156 ops/sec
Result: Node.js crypto 1.8x faster

💡 Key Insight: Rust delivers 1.37x speedup for large objects (1000 keys). For smaller objects, JavaScript's optimized V8 engine is faster due to FFI overhead.

Run benchmarks yourself:

npm run bench
npm run bench:memory

Memory Usage

Memory consumption comparison (lower is better):

Very Large Objects (10,000 keys)

JavaScript hash:          0.003 KB per operation
Rust fastHashOptimized:   0.001 KB per operation
Memory savings: 61.6% ✓✓✓

Summary

  • Small objects: Rust uses similar memory to JavaScript
  • Medium objects: Rust uses slightly less memory
  • Large objects (1000 keys): JavaScript uses ~50% less memory
  • Very large objects (10,000+ keys): Rust saves 61.6% memory

The memory advantage appears at very large object sizes where Rust's efficient string handling outweighs JavaScript's GC optimizations.

Use Cases

✅ Perfect For:

  • Memoization - Cache expensive function results
  • Request caching - Cache API responses by request parameters
  • React/Vue rendering - Fast prop change detection
  • Data deduplication - Find duplicate objects in large datasets
  • Cache keys - Generate stable cache keys from objects

❌ Not Ideal For:

  • Equality checking - Use regular === or fast-deep-equal
  • Small objects - V8 is already fast enough
  • Frequent small hashes - FFI overhead dominates

Why Not Deep Equality?

We initially built this as a deep equality checker, but discovered that V8 is faster than Rust for traversing objects due to FFI overhead.

However, hashing is perfect for Rust because:

  1. We only cross the FFI boundary once
  2. Rust's ahash algorithm is genuinely faster than JS
  3. The use case (caching) benefits from Rust's speed

See LEARNINGS.md for the full story.

How It Works

JavaScript Object → JSON.stringify (V8 optimized)
                 → Cross FFI once
                 → ahash in Rust (fast!)
                 → Return hash string

The key optimization: We let V8 handle serialization (what it's good at), then do hashing in Rust (where we're faster).

Requirements

  • Node.js >= 10
  • Automatically downloads pre-built binaries for:
    • macOS (x64, ARM64)
    • Linux (x64, ARM64)
    • Windows (x64)

Building from Source

# Install Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Build
npm install
npm run build

# Test
npm test

# Benchmark
npm run bench

License

MIT

Contributing

Contributions welcome! This project demonstrates:

  • Building high-performance Node.js natives modules with Rust
  • When to use Rust vs JavaScript
  • Optimizing FFI boundaries
  • Real-world Rust + napi-rs patterns

Acknowledgments