Usage Guide & Core Concepts
APCu operates by storing PHP variables in a fixed-size segment of shared memory, making them accessible to all PHP processes running under the same server configuration. Understanding its internal architecture helps in using it effectively.
Much of this information is derived from the project's TECHNOTES.txt file.
Shared Memory Allocator (SMA)
At the heart of APCu is the Shared Memory Allocator (SMA), which manages the single, large block of shared memory configured via the apc.shm_size directive.
- Allocation: When you store a variable, the SMA finds a free block of memory large enough to hold it. It uses a best-fit strategy to minimize fragmentation.
- Fragmentation: Over time, as items of different sizes are added and removed, the free memory can become fragmented into many small, non-contiguous blocks. When APCu cannot find a large enough contiguous block for a new item, it may trigger an
expungeoperation. - Defragmentation: As of version 5.1.25, APCu can defragment the shared memory by moving existing cache entries to consolidate free space. This reduces the need to completely clear the cache when memory is fragmented.
Cache Structure
The cache itself is implemented as a hash table, where each "slot" in the table is a linked list of cache entries.
- Hashing: When you access a key, APCu computes a hash of the key string to determine which slot to look in.
- Lookup: It then traverses the linked list in that slot, comparing the full key of each entry until a match is found.
This is why the apc.entries_hint INI directive is important. A well-sized hash table minimizes the length of these linked lists, reducing collisions and speeding up lookups.
Persistence and Serialization
PHP variables from a single request's memory cannot be directly shared with other processes. They must be copied (persisted) into the shared memory segment.
- Simple Types: Simple types like
null, booleans, integers, and floats are copied directly. - Complex Types: Strings, arrays, and objects require a more complex process.
- Deep Copying: APCu performs a deep copy of arrays and objects, traversing their structure and copying all their constituent parts into the shared memory segment. To make this data relocatable and independent of memory addresses, all internal pointers are converted to offsets from the start of the entry's memory block.
- Serialization: For very complex structures, objects, or when a custom serializer is configured, APCu uses a serialization mechanism. The
apc.serializerINI directive controls which serializer to use. The default isphp, which uses PHP's standardserialize()/unserialize()functions. Other serializers, likeigbinary, can be used for better performance and smaller storage size.
When you apcu_fetch() an item, this process is reversed (unpersist), and a new copy of the variable is created in the current PHP process's memory.
Locking and Concurrency
Because multiple PHP processes can read from and write to the same shared memory segment simultaneously, APCu must manage concurrency to prevent data corruption.
- Read-Write Locks (rwlocks): By default, APCu uses read-write locks. This mechanism allows any number of processes to read from the cache at the same time, but ensures that only one process can write to the cache at a time. All read operations are blocked while a write is in progress.
- Atomic Operations: For
apcu_inc()andapcu_dec(), APCu uses hardware-level atomic operations. This is much faster than acquiring a full write lock, making these functions ideal for high-concurrency counters.
Expiration and Eviction
Cached items are removed from memory under two conditions:
-
Expiration (TTL): When you store an item, you can provide a Time-To-Live (TTL) in seconds. APCu will consider the item expired after this time has passed. Stale entries are not removed immediately; they are typically cleaned up (
expunged) during a subsequent write operation or when memory is full. -
Eviction: When the shared memory segment is full and a new item needs to be stored, APCu triggers an
expungeprocess. It first tries to remove all expired items. If that doesn't free enough space, it may defragment memory. If space is still insufficient, APCu will clear the entire cache to make room.