UNPKG

mem100x

Version:

⚡ The FASTEST MCP memory server ever built - 66k+ entities/sec with intelligent context detection

207 lines 7.29 kB
"use strict"; /** * High-Performance Bloom Filter * Probabilistic data structure for O(1) existence checks * Now with ultra-fast non-cryptographic hashing */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BloomFilter = void 0; const xxhash_wasm_1 = __importDefault(require("xxhash-wasm")); // Initialize xxhash instance let hashInstance = null; class BloomFilter { size; numHashes; bits; itemCount = 0; initialized = false; constructor(expectedItems = 10000, falsePositiveRate = 0.01) { // Calculate optimal size and hash functions this.size = Math.ceil(-expectedItems * Math.log(falsePositiveRate) / (Math.log(2) ** 2)); this.numHashes = Math.ceil(this.size / expectedItems * Math.log(2)); this.bits = new Uint8Array(Math.ceil(this.size / 8)); } // Initialize the hash functions async init() { if (!this.initialized) { hashInstance = await (0, xxhash_wasm_1.default)(); this.initialized = true; } } // Synchronous fallback for immediate use murmur3(str, seed) { let h1 = seed; const c1 = 0xcc9e2d51; const c2 = 0x1b873593; const r1 = 15; const r2 = 13; const m = 5; const n = 0xe6546b64; for (let i = 0; i < str.length; i++) { let k1 = str.charCodeAt(i); k1 = Math.imul(k1, c1); k1 = (k1 << r1) | (k1 >>> (32 - r1)); k1 = Math.imul(k1, c2); h1 ^= k1; h1 = (h1 << r2) | (h1 >>> (32 - r2)); h1 = Math.imul(h1, m) + n; } h1 ^= str.length; h1 ^= h1 >>> 16; h1 = Math.imul(h1, 0x85ebca6b); h1 ^= h1 >>> 13; h1 = Math.imul(h1, 0xc2b2ae35); h1 ^= h1 >>> 16; return h1 >>> 0; } add(item) { const hashes = this.getHashes(item); for (const hash of hashes) { const index = hash % this.size; const byteIndex = Math.floor(index / 8); const bitIndex = index % 8; this.bits[byteIndex] |= (1 << bitIndex); } this.itemCount++; } contains(item) { const hashes = this.getHashes(item); for (const hash of hashes) { const index = hash % this.size; const byteIndex = Math.floor(index / 8); const bitIndex = index % 8; if ((this.bits[byteIndex] & (1 << bitIndex)) === 0) { return false; } } return true; } getHashes(item) { const hashes = []; if (hashInstance && this.initialized) { // Use ultra-fast xxhash when available const hash1 = hashInstance.h32(item, 0); const hash2 = hashInstance.h32(item, 1); // Use double hashing technique for (let i = 0; i < this.numHashes; i++) { hashes.push(Math.abs(hash1 + i * hash2)); } } else { // Fallback to fast synchronous hash const hash1 = this.murmur3(item, 0); const hash2 = this.murmur3(item, 1); for (let i = 0; i < this.numHashes; i++) { hashes.push(Math.abs(hash1 + i * hash2)); } } return hashes; } clear() { this.bits.fill(0); this.itemCount = 0; } getStats() { let setBits = 0; for (const byte of this.bits) { for (let i = 0; i < 8; i++) { if (byte & (1 << i)) setBits++; } } return { size: this.size, numHashes: this.numHashes, items: this.itemCount, fillRate: setBits / this.size }; } // Serialize the Bloom filter to a buffer for persistence serialize() { // Create header with metadata const header = Buffer.alloc(16); header.writeUInt32BE(this.size, 0); header.writeUInt32BE(this.numHashes, 4); header.writeUInt32BE(this.itemCount, 8); header.writeUInt32BE(this.bits.length, 12); // Combine header and bits return Buffer.concat([header, Buffer.from(this.bits)]); } // Deserialize a Bloom filter from a buffer static deserialize(buffer) { // Read header const size = buffer.readUInt32BE(0); const numHashes = buffer.readUInt32BE(4); const itemCount = buffer.readUInt32BE(8); const bitsLength = buffer.readUInt32BE(12); // Create a new filter with the same parameters const filter = Object.create(BloomFilter.prototype); filter.size = size; filter.numHashes = numHashes; filter.itemCount = itemCount; filter.initialized = false; // Copy bits filter.bits = new Uint8Array(bitsLength); buffer.copy(filter.bits, 0, 16, 16 + bitsLength); return filter; } // Save to file async saveToFile(filePath) { const fs = await Promise.resolve().then(() => __importStar(require('fs/promises'))); const buffer = this.serialize(); await fs.writeFile(filePath, buffer); } // Load from file static async loadFromFile(filePath) { const fs = await Promise.resolve().then(() => __importStar(require('fs/promises'))); try { const buffer = await fs.readFile(filePath); const filter = BloomFilter.deserialize(buffer); // Initialize hash functions await filter.init(); return filter; } catch (error) { // File doesn't exist or is corrupted return null; } } } exports.BloomFilter = BloomFilter; //# sourceMappingURL=bloom-filter.js.map