Release v2.7.0 LivePHP 8.1 – 8.6

Sparse Dynamic Arrays
At C Speed for PHP

Deterministic memory scaling, lexicographic ordered walks, zero-copy bulk extraction, and native TTL cache storage.

pie install orieg/judy
Interactive Guide → Full API Reference Judy Cache PSR-16
What's New in v2.7.0

Native TTL Caching & Rust Expanse Engine

PHP Judy 2.7.0 introduces Judy::STRING_TO_ENTRY — packing values with uint32 expiry timestamps and 16-bit metadata flags directly into native C struct entries with zero secondary indexes, plus pure-Rust Expanse backend integration.

Judy::STRING_TO_ENTRY In-C pruneExpired() --with-expanse
TTL Pruning (100k) 12.9 ms (0 B heap)
Dual-Trie Savings -50% Key Index RAM
Backend Option libJudy + Expanse
Type Matrix

Pick the optimal Judy array layout for your key/value shape and performance requirements.

Keys / Values
int → bool
Memory Footprint
1 bit / entry
Key Ordering
Unsigned integer word
Best For
Seen-sets, Bloom filters, IDs

Presence-only set. The cheapest possible data structure in PHP. Millions of integer IDs stored in single megabytes of memory.

Keys / Values
int → int
Memory Footprint
Exact (JudyLMemUsed)
Key Ordering
Unsigned integer word
Best For
Atomic counters, ID mapping

Sparse integer map. Supports high-speed in-C $j->increment($key, $amount) without read-modify-write penalties.

Keys / Values
string → any (zval)
Data Structure
JudySL Radix Trie
Key Ordering
Lexicographic (bytes)
Best For
Prefix walks, symbol tables

Trie-ordered string map. Supports $O(\text{range})$ key-space slicing, bounded iteration, and fast prefix matching.

Keys / Values
string → int
Data Structure
JudyHS Hash Index
Lookups
Fastest Point Read
Best For
High-throughput dictionaries

JudyHS length-prefixed hash table. Delivers the absolute fastest random point-lookups for string keys.

Keys / Values
string → entry (TTL + flags)
Storage Model
Single-Trie Packed C Struct
Eviction
Single-Pass In-C (12.9 ms)
Best For
PSR-16 caches, worker stores

Unified cache entry type. Eliminates secondary expiries tries by storing expiry timestamps and metadata flags in the C struct node.

Code Showcase

Clean, idiomatic PHP examples demonstrating core Judy capabilities.

<?php
// Create an integer-to-mixed sparse array
$judy = new Judy(Judy::INT_TO_MIXED);

// ArrayAccess CRUD operations
$judy[42] = ['user' => 'nicolas', 'role' => 'admin'];
$judy[10_000_000] = 'sparse high index';

isset($judy[42]);         // true
count($judy);             // 2 (O(1) population count)
unset($judy[10_000_000]);

// Foreach iterates in strict key order
foreach ($judy as $id => $data) {
    var_dump($id, $data);
}
<?php
$j = new Judy(Judy::STRING_TO_MIXED);
$j['app.cache.user.1'] = 'alpha';
$j['app.cache.user.2'] = 'beta';
$j['app.session.42']    = 'active';

// Seek operations (key-space bounds)
$firstKey = $j->first();                   // "app.cache.user.1"
$nextKey  = $j->searchNext($firstKey);    // "app.cache.user.2"

// High-speed bounded key extraction in single C traversal
$userKeys = $j->keys('app.cache.', 'app.cache.z');

// Count items in key range without allocating PHP arrays
$count = $j->size('app.cache.', 'app.cache.z'); // 2
<?php
// Construct directly from PHP array in a single C pass
$data = ['a' => 10, 'b' => 20, 'c' => 30];
$j = Judy::fromArray(Judy::STRING_TO_INT, $data);

// Bulk insert / replace
$j->putAll(['d' => 40, 'e' => 50]);

// Bulk point-lookup (1.9x faster than individual lookups)
$values = $j->getAll(['a', 'c', 'e']); // ['a' => 10, 'c' => 30, 'e' => 50]

// Export back to native array (3.1x faster than foreach)
$array = $j->toArray();
<?php
$counters = new Judy(Judy::STRING_TO_INT);

// Atomic in-place increment (creates key at 0 if absent, then adds delta)
$counters->increment('hits:page:index', 1);
$counters->increment('hits:page:index', 5);

// Aggregation runs directly across libJudy C memory
$totalHits = $counters->sumValues();
$avgHits   = $counters->averageValues();
<?php
// Native compound cache entry type (v2.7.0)
$cache = new Judy(Judy::STRING_TO_ENTRY);

// Store payload with 60s TTL and 16-bit metadata flags
$cache->set('session:abc', ['auth' => true], $ttl = 60, $flags = 0x0001);

// Fetch value with output references for metadata
$val = $cache->get('session:abc', $expiresAt, $flags);

// Single-pass in-C TTL eviction (0 PHP heap allocations)
$evicted = $cache->pruneExpired();
Performance & Footprint

Empirically measured memory consumption and execution latency against standard PHP data structures.

Memory: 1,000,000 Integer Entries

Measured VmRSS in separate process.

Judy::BITSET0.15 MB (-99.7%)
Judy::INT_TO_INT8.2 MB (-79%)
SplFixedArray16.0 MB (-59%)
Native PHP Array39.1 MB (Baseline)

Namespace Invalidation (1M Keys)

Time to delete a 1,000-key slice from 1M elements.

PHP Judy (deleteRange)53 µs (17,000x faster)
APCu (Regex Key Sweep)81,000 µs (81 ms)
Symfony ArrayAdapter900,000 µs (900 ms)
Installation & Setup

Multiple installation methods supported across all modern PHP environments.

PIE (Recommended)

pie install orieg/judy

The official PHP Installer for Extensions.

PECL

pecl install judy

Standard PECL distribution package.

Docker

RUN pecl install judy && docker-php-ext-enable judy

Bundled libJudy requires no external packages.

With Rust Expanse Engine

./configure --with-expanse=/usr

Link with pure-Rust Judy engine.