Debugging WINCACHE using Visual Studio – Cache management

Previous Post

In the last post I talked about setting important breakpoints. In this post I will talk about how different cache is managed using shared memory which is part of the function I told you to put breakpoint in. And yes it is the most important point of my second question in the last blog. How WINCACHE is initialized? I am not going to talk about first 15-20 lines as those are self explanatory. In those lines we do the following (BTW, for people who don’t know what I am talking about. I am talking about PHP_MINIT_FUNCTION function in the file named php_wincache.c):

  • Call the mandatory initialization functions which initializes the WINCACHE INI directives to default value or the value they are set in the PHP.INI file. Details can be found inside function zend_register_ini_entries in the file zend_ini.c (in case you are interested).
  • Check if the one that is set in the PHP.INI file is within the limits or not. if not set it to min/max value depending on where they are.
  • If WINCACHE is disabled for CLI immediately return without doing anything.
  • A not so important thing, we did this enhancement where we ensure that Output Code Cache size is at least 3 times bigger than File Cache size. We do check this and set this appropriately here. If you have this condition your output of WINCACHE.PHP file will show the entry in yellow and hovering the mouse will display the reason as outlined above.
  • Next we do all the shared memory/cache initialization and this is the topic of the blog today.
  • Override original Zend functions.

If you are familiar with shared memory concept on UNIX, it will not be very difficult to transition the knowledge on Windows. On Windows you have similar functions like CreateFileMapping, OpenFileMapping, MapViewOfFileEx, UnMapViewOfFileEX, CloseHandle, FlushViewOfFile. If you are familiar with UNIX shared memory functions you will understand quickly what these functions do. Please follow the links for explanation and I recommend it as must for UNIX developers because without knowing these API it will be difficult understanding the cache management concept of WINCACHE. Also go through the below links:

In WINCACHE code we create named share memory. In order to make name unique, we append parent process id and name salt if one is specified using WINCACHE.NAMESALT directive (look at filemap_initialize function in file wincache_filemap.c). Below is how cache is initialized/created:

  • Call to function filemap_global_initialize(). This creates the basic information filemap. The name of this shared memory is WINCACHE_FILEMAP_INFORMATION_*. This consists of all the information about various shared memory and how to get to that.
  • Before creating file cache/output code cache/relative path cache shared memory, we see in the filemap information if they have been already created by some other process or not. if they are already created we use OpenFileMapping to open it and MapViewOfFile to map it in the process own address space.
  • Output code cache shared memory is different in the case that we try to map it at the same memory address in all the process. The reason being this cache contains pointers to zend internal data structures and hence the need for mapping this shared memory at the same address. if mapping to same address fails, we create a local only copy of output code cache and use that for the process in question. In case of local cache, the name is made unique to the process by appending process id rather than parent process id. All this is done within PHP_MINIT_FUNCTION.
  • Relative path cache is initialized within the function aplist_initialize in the file wincache_aplist.c.
  • Once all the initialization happens properly, WINCACHE is all set to start caching. The code simply overrides original zend functions with the ones written specifically for WINCACHE which does the caching.

Typically while initializing file cache/output code cache, following happens:

  • The corresponding context gets created. This is the top level structure (example ocache_context) which contains all the information about the cache namely filemap (which contains information about shared memory), lock as well as allocator.
  • This initialization overall creates and initializes filemap, lock and allocator.

Hopefully this will help you in understanding the basics of shared memory management inside WINCACHE code. Happy debugging and till we meet again good bye .

Thanks,

Don.

No Comments