mem100x
Version:
⚡ The FASTEST MCP memory server ever built - 66k+ entities/sec with intelligent context detection
207 lines • 7.29 kB
JavaScript
;
/**
* 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