APC, full name: AlternativePHPCache, officially translated as "optional PHP Cache ". It provides us with a framework for caching and optimizing PHP intermediate code. APC cache consists of system cache and user data cache.
APC, full name: Alternative PHP Cache, officially translated as "optional PHP Cache ". It provides us with a framework for caching and optimizing PHP intermediate code. APC cache consists of system cache and user data cache.
- System cache: APC caches the compilation results of the PHP file source code and compares the time Mark before each call. If it does not expire, it runs with the cached intermediate code. The default cache is 3600 s (one hour ). However, this will still waste a lot of CPU time. Therefore, you can set the system cache in php. ini to never expire (apc. ttl = 0 ). However, you need to restart the WEB server after the php code is modified. This type of cache is usually used.
- The user data cache is read and written by the user using the apc_store and apc_fetch functions when writing PHP code. If the data volume is small, you can try it. If the data volume is large, it would be better to use a more specific memory cache solution similar to memcache.
In APC, we can also enjoy the features of APC that cache the upload progress of large files. set apc in ini. rfc1867 is set to 1, and a hidden domain APC_UPLOAD_PROGRESS is added to the form. The value of this field can generate a random hash to ensure uniqueness. In the previous article, the implementation principles of PHP file Upload progress are described in more detail.
Interaction between APC and PHP kernel
APC is added to the PHP System as an extension. Therefore, according to PHP's extension specifications, it will have macro-defined functions such as PHP_MINIT_FUNCTION, PHP_MSHUTDOWN_FUNCTION, PHP_RINIT_FUNCTION, and PHP_RSHUTDOWN_FUNCTION. In PHP_MINIT_FUNCTION (apc), apc_module_init is called. in this function, zend_compile_file is assigned a value to replace the built-in compiling file process, this inserts the functions and related data structures of APC into the entire PHP system.
There is a problem here. what if there are multiple replacement operations for zend_compile_file? In actual use, this situation often occurs. for example, when we use xdebug extension and apc again, how does PHP handle it? No matter which extension is used, when zend_compile_file is used for replacement, there will be a compile_file function (used for replacement), and an extended scope, an old compilation function: old_compile_file. It is equivalent to retaining a reference to the previous compilation function in each extension to form a one-way linked list. In addition, all the final op_array is generated through old_compile_file in the new zend_compile_file, that is, the compilation process will be passed to the zend_compile_file implementation of PHP along this one-way linked list. During the transfer process, each node passes through a node, these nodes add their own data structures to meet specific requirements.
APC internal storage structure
In APC, the system cache and user cache are stored with two global variables. the code logic layer isolates the two caches. of course, the implementation process and data structure of these two types of storage are the same. they are all apc_cache_t types, as shown below:
/* {Struct definition: apc_cache_t */struct apc_cache_t {void * shmaddr; address of the local process that shares the cache cache_header_t * header; cache header, slot_t ** slots stored in the shared memory; cache slots array, which is stored in the shared memory int num_slots; number of slots stored in the cache int gc_ttl; the maximum ttl int TTL of the slot in the GC list. if the access time to the slot is greater than the ttl, remove the slot apc_expunge_cb_t expunge_cb; /* cache specific expunge callback to free up sma memory */uint has_lock; mark for possible causes of recursive locks of the same process/* flag for possible recursive locks within the same process */};/*}}}*/
For a cache, the apc_cache_t type variable is its entry, which contains some global information about the cache. Each cache has multiple cache slots, which are included in the slots field. the number of slots is included in the num_slots field. the slots process time is controlled by the ttl field. By default, the number of system caches is 1000 for user cache and system cache. In fact, 1031 APC files are created. that is to say, by default, APC can cache the intermediate code of at least 1031 files. Of course, this value also needs to consider the memory size, the distribution after calculating the slot key, and so on. More cache statistics are stored in the header field. the header field structure is cache_header_t, as shown below:
Struct cache_header_t {apc_lck_t lock; read/write lock, exclusive blocking of the cache lock apc_lck_t wrlock; write lock, to prevent the cache from being full of unsigned long num_hits; number of cache hits unsigned long num; cache miss count unsigned long num_inserts; total number of inserted cache hits unsigned long expunges; total number of cleanups slot_t * deleted_list; point to the linked list time_t start_time; the time when the above counter was reset zend_bool busy; when apc is busy clearing the cache, it tells the client that the status Mark int num_entries; the number of measured entities size_t mem_size; the size of the memory used for caching apc_keyid_t lastkey; the last written key cached by the user };
A cache contains multiple slots. each slot is a slot struct variable. its structure is as follows:
Struct slot_t {apc_cache_key_t key; the key apc_cache_entry_t * value of the slot; the slot value slot_t * next; the next slot in the linked list is unsigned long num_hits; number of hits of this bucket/* number of hits to this bucket */time_t creation_time; slot initialization time time_t deletion_time; time when the slot is removed from the cache/* time slot was removed from cache */time_t access_time; last accessed time of the slot };
Each slot contains a key, which is stored in an apc_cache_key_t struct and a value, which is stored in an apc_cache_entry_t struct. As follows:
typedef struct apc_cache_key_t apc_cache_key_t; struct apc_cache_key_t { apc_cache_key_data_t data; unsigned long h; /* pre-computed hash value */ time_t mtime; /* the mtime of this cached entry */ unsigned char type; unsigned char md5[16]; /* md5 hash of the source file */ };
The structure is described as follows:
- Data field apc_cache_key_data_t type, a consortium, stores the associated information of the key. for example, for system cache, it may store the file path or OS file device/inode; the user cache may store the user-defined identity or identity length.
- H: the complete path of the field file or the hash value of the user-defined identity. the hash algorithm is the built-in time33 algorithm of PHP, or the sum of the values of the device and inode where the file is located.
- Modification time of the cached object in the mtime field
- Type field APC_CACHE_KEY_USER: User cache; APC_CACHE_KEY_FPFILE: System cache (full path available); APC_CACHE_KEY_FILE: System cache (file search required)
- The md5 value of the MD5 field file content. This field is different from the previous four fields. it is optional and can be enabled or disabled through apc. file_md5 in the configuration file. This value is created when the object is initialized. When we see the md5 value of the source file, we think of a previous optimization on the access path query in the MySQL data table. when the data volume reaches a certain level, we directly query the path field at the beginning, even if the index is used, it will still be slow. after testing in various schemes, a new md5 value query about the access path is used to solve the problem.
Apart from the entry point, APC also distinguishes the system cache and user cache in the final data storage. In _ apc_cache_entry_value_t, the two correspond to file and user respectively.
Typedef union _ apc_cache_entry_value_t {struct {char * filename;/* absolute path to source file */zend_op_array * op_array; op_array apc_function_t * functions; /* array of apc_function_t's */apc_class_t * classes;/* array of apc_class_t's */long halt_offset; /* value of _ COMPILER_HALT_OFFSET _ for the file */} file; space used by the file structure system cache, including the file name, struct {char * info; int info_len; zval * val; unsigned int ttl; Expiration Time} user; space used by the ser struct user cache} apc_cache_entry_value_t;
:
APC cache storage structure
Initialization
In the module initialization function expanded by APC (PHP_MINIT_FUNCTION (apc), APC calls the apc_module_init function to initialize the global variables required by the cache. for example, in the system cache, apc_cache_create is called to create the global variable apce_cache, by default, the memory space required by 1031 slots will be allocated. the user cache will also call the same method to create a cache, which is stored in another global variable apc_user_cache, by default, 4099 memories are allocated. The number of space allocated here is a prime number. in the APC code, there is a primes table for different numbers of prime numbers (in the apc_cache.c file ). The calculation of prime numbers is to directly traverse the prime number table and find the first prime number in the table that is larger than the number to be allocated.
Cache key generation rules
Each slot in the APC cache has a key. The key is of the apc_cache_key_t struct type. in addition to key-related attributes, the key is the generation of the h field. The h field determines where the element falls in the slots array. User cache and system cache have different generation rules.
- The user cache uses the apc_cache_make_user_key function to generate a key. The key string passed by the user depends on the hash function in the PHP kernel (the hash function used by PHP's hashtable: zend_inline_hash_func) to generate the h value.
- The system cache uses the apc_cache_make_file_key function to generate a key. Different solutions are treated differently through the APC. stat switch, which is the configuration item of apc. When apc. stat = On is enabled, the compiled content is automatically re-compiled and cached if it is updated. The h value is the value obtained by adding the device and inode of the file. When apc. stat = off is disabled, the Web server must be restarted to make the updated content take effect after the file is modified. In this case, the h value is generated based on the file path address, and the path here is the absolute path. Even if you are using a relative path, you will also find the PG (shortde_path) location file to get the absolute path. Therefore, using the absolute path will skip the check, which can improve the code efficiency.
Add cache process
Taking the user cache as an example, the apc_add function is used to add content to the APC cache. If the key parameter is a string, APC generates a key based on the string. if the key parameter is an array, APC traverses the entire array to generate a key. Based on these keys, APC will call _ apc_store to store values in the cache. Because this is the user cache, the current cache is apc_user_cache. The write operation is the apc_cache_make_user_entry function, which finally calls apc_cache_user_insert to perform traversal query and write operations. Correspondingly, when the system cache uses apc_cache_insert to execute the write operation, it will eventually call _ apc_cache_insert.
The execution process is similar to that of the user cache or system cache. The steps are as follows:
- Perform the remainder operation to locate the location of the current key in the slots array: cache-> slots [key. h % cache-> num_slots];
- After locating the slots array, traverse the slot linked list corresponding to the current key. if the slot key matches the key to be written or the slot expires, clear the current slot.
- Insert a new slot after the last slot.