Podcast on Running PHP on Windows

Peter Laudati & Dmitry Lyalin host the edu-training Connected Show developer podcast on cloud computing and interoperability. I met Peter in Chicago during Tek-X and we along with Don and Wade recorded a podcast on evolution of PHP on the Windows Platform. We talked about the improvements made to Windows in order to support PHP, including: Fast CGI, WinCache, PHP 5.3, the Web PI, and the SQL Server driver for PHP. Check out episode #31, “PHP On Windows” on Connected Show. Interview starts at 24:31.


If you like what you hear, check out previous episodes of the Connected Show at www.connectedshow.com.  You can subscribe on iTunes or Zune.  Peter and Dmitry publish new episodes approximately every two weeks!


WordPress widget to show WinCache statistics

Ruslan (http://ruslany.net), who is Program Manager for WinCache project, has been showing WinCache statistics on the right sidebar of his website for quite some time. Few weeks ago I decided to do the same but instead of editing theme source code and add the information there, I decided to write a standalone wordpress widget. Two days ago I finally wrote the widget which is aptly called wincache-stats. It shows statistics in a table format. First column of the table show cache type and number of entries in cache, second column show hit count and hit ratio and third column show miss count and miss ratio. It can be see in action on http://www.ksingla.net. I submitted the widget to wordpress.org yesterday and it has been approved. So this is available for download from wordpress.org here. If you want to look at the source code, you can see it here. Below is a snapshot of the wincache-stats widget.
You can choose what statistics to show in the wordpress admin interface. Picture below shows admin interface of wincache-stats widget.
I hope some of the WinCache users use this widget on their website to see WinCache usage and in the process, help us spread the word about WinCache. If you want to report a bug or request a feature, please leave a comment to this blog.

What’s new in WinCache 1.1 Beta2 and what’s next

After WinCache 1.0 release, two most requested features were user cache and session cache. We added both of these features in WinCache 1.1 beta1. We are very happy with the rate of adoption of user cache by PHP application developers. Many application developers have already added support for WinCache user cache in their applications and many are in the process of adding it. Earlier we were planning to add only these two features in WinCache 1.1 and then do more performance optimizations in WinCache 1.2 but later we decided to add these additional optimizations in 1.1 release itself. Because of this, we did beta2 release which has file change notification and function hooks support along with some small feature additions. Below is the full list of features which got added to WinCache 1.1 up to beta2 release.
1.       User cache APIs – We have added APIs like wincache_ucache_get, wincache_ucache_set etc. (see full list here) which can be used to store and retrieve application data from the cache. Since the cache is shared among all PHP processes under an application pool, application developers can calculate data once, store it in the cache and then retrieve it in next request instead of calculating it every time. Database query results, site counters etc. are good candidates to be stored in user cache. These APIs behave much like user cache APIs available in APC to make it easier for developers to use existing code written for APC.
2.       WinCache session handler – PHP provides three session handlers (files, shm, user) out of the box of which shared memory (shm) handler doesn’t work on windows. Session handler “files” is the most commonly used session handler on windows which is slow as it requires file read on every request. We have implemented a session handler in WinCache which keeps session data in shared memory which is much faster compared to files. Since session data is expected to survive PHP and IIS process recycles, data is persisted on disk by WinCache in the folder specified by session.save_path. Since session.save_path is not a system level configuration, WinCache creates a separate session cache for different values of session.save_path. WinCache 1.1 stored this data in memory allocated for user cache but WinCache beta2 allocates separate memory for session cache.
3.       File change notification – WinCache now registers for change notifications to all folders under which a file is requested by file cache or opcode cache. When a file change notification is received, that file is removed from all the caches immediately. Doing this without incurring performance penalty required us to make all processes not listen to all the folders. So we designed a distributed change notification infrastructure which works without any master. Of all PHP processes running on the system for an application pool, only one of them listens to one folder. Other processes detects that a listener is present for the folder and do nothing. If a process dies, another process detects this situation and registers for a change listener itself. We made sure that no change is ever missed by this system and this system can easily scale to 100s of folders.
4.       Function hooks – With file cache and file change notification infrastructure in place, we decided to rewrite some PHP APIs like file_get_contents, is_file etc on top of this infrastructure to make them faster. For this we have added ability to define function hooks in WinCache.  WinCache 1.1 beta2 include this infrastructure but doesn’t include any function hooks. I am in the process of rewriting some functions and we will enable these hooks in WinCache 1.1 RC release.
5.       In WinCache 1.0, we create separate cache for PHP processes running under one process. This didn’t work too well in web garden scenarios. WinCache 1.1 has solved this problem by sharing cache for all PHP processes running under worker processes belonging to one application pool. If application pool id is not available (as in Apache), it will switch to old behavior.
6.       Added optional boolean argument summaryonly to all WinCache info functions. Ruslan requested this feature so that wincache_ocache_fileinfo function calls made by his wordpress widget on his site (http://ruslany.net) are faster. And based on customer feedback we changed wincache_ucache_info to accept an optional key to make it return information on just one user cache entry and exposed user cache entry size in each entry.
7.       Drupal application developers requested us to add wincache_lock, wincache_unlock APIs and we have added these in 1.1 Beta2 release. By default lock created by wincache_lock is scoped to all PHP processes sharing the cache. If you want a global lock, set optional argument isglobal to true.
8.       WinCache statistics page (wincache.php) has been changed to show user cache and session cache data and fixed bugs reported by customers on http://pecl.php.net/bugs/.
We are planning to add replacement APIs for PHP functions which deal with files in WinCache 1.1 RC release. We will also enable function hooks so that calls to PHP file APIs gets re-routed to these APIs. And as always, we will implement feature requests and fix bugs reported by you.

Comparing WinCache user cache APIs with other caches

 WinCache 1.1 beta release added two new major features to WinCache. These are user cache APIs which can be used to store custom data in the cache and “wincache” session handler. User cache APIs was the biggest feature gap WinCache 1.0 had compared to other caching solutions which are frequently used on Linux. WinCache 1.1 release was aimed to fill this gap. WinCache session handler, which internally uses user cache, is included so that php session data can be stored in in-memory shared cache instead of on disk which tend to be slower. Read more about these features here.



Both the features are very well received by customers and many open source application developers are working to include support for these in the applications. If you want to use WinCache user cache APIs to speed up your php application, it will be useful to first look for code which is doing that with other caches like APC, Xcache and Eaccelerator. If the application is written to make use of a caching solution, chances are that there will be plug-in available for APC or Xcache or Eaccelerator. Once you have the code you can use the following table to easily map API calls to other caches to WinCache.


Other than unset_by_prefix functionality in Xcache, WinCache provides a superset of the functionality offered by other caching solutions. Another piece missing in WinCache is APIs similar to eaccelerator_lock and eaccelerator_unlock. We are trying to understand scenarios in which these APIs will be required by developers while working with user cache APIs. If we see these are required, we will add these in future. I hope this table makes it easy to use WinCache user cache APIs and port code written for existing caches.

Inconsistencies in wincache statistics page explained

Problem description


Many customers running WinCache reported seeing different cache statistics on consecutive requests to wincache.php. Specifically, cache uptime and opcode cache summary returned second time by wincache.php was completely different than the data returned first time. Occasionally data shown in the opcode cache summary table didn’t match the chart displayed on its side. Many customers correctly guessed that this happens because there are multiple cache instances present in different php-cgi processes but thought that none of the PHP processes are sharing cache data and were worried about excessive memory usage by WinCache. I have been replying to many customers personally and posting on forums explaining why they see this behavior but as more and more customers are using WinCache, this question is becoming more common. Ruslan who is PM for WinCache suggested writing a blog post to help customers understand the reason. So here you go.


Detailed explanation


WinCache creates many memory segments which are shared among all the php-cgi processes launched by a particular IIS worker process. For simplicity sake I will use the term “all php processes” to refer to “all php processes launched by one IIS worker process”. In version 1.0, WinCache creates 5 shared memory segments. Mostly these segments are shared successfully among all the php processes. In fact 4 shared segments are always shared but memory segment for opcode cache is sometimes not shared. Reason for this is that 4 of the 5 memory segments store data structures which are completely defined by us. Anytime we need to store a pointer in the shared segment which points to some other data in the shared segment, we define pointer as simple integer which is then set to offset from start of memory segment. This way other processes can reach the data pointed by this pointer even when absolute address of the data might be different. In contrast, data stored in opcode cache is defined by the PHP engine and include many absolute pointers. These pointer values cannot be changed to offsets without incurring a very heavy performance penalty which will totally defy the purpose of WinCache. For this reason, we try to map the global opcode cache segment at same address in all processes using MapViewOfFileEx which can possibly fail if the address is already occupied. All other caches doesn’t have this restriction and are mapped anywhere which mostly succeed. If we fail to map the opcode cache at a particular address, we create another opcode cache in processs local memory so that requests processed by this process are also very fast. Typically this happens for 5%-10% of php processes. Below figures illustrates state of the caches in a normal php process (figure 1) and in a process which ends up creating a local cache (figure 2). For more information on these caches, read my previous blog.


Local Cache Explanation

Now that you understand this design, all the anomalies seen in responses of wincache.php can be explained. If the process which processes request to wincache.php has a local cache, opcode cache data will be different from the one shown when request is handled by a process which is using global opcode cache. Also since cache uptime in wincache.php is picked from opcode cache (ocache_fileinfo), it will be age of either global opcode cache or local opcode cache. Reason why chart sometimes didn’t match opcode cache summary is because request to draw the chart is sent separately. If the chart draw request reaches a process which has different cache structure than the one which returned summary data, there can be a mismatch.


Improvements in WinCache 1.0.1


In WinCache 1.0.1, we have made few changes to wincache.php which will make all this a little less confusing. Since cache uptime can be different for file cache and opcode cache, we have moved the cache uptime field to opcode cache and file cache summary tables. So you will now see two cache uptimes. File cache uptime will reflect age of global file cache and opcode cache uptime will reflect age of global or local opcode cache. We also added cache scope property in opcode cache summary table which will be either “global” or “local”. This will indicate if the opcode cache data you are looking at is for global cache or a local cache. To fix the chart discrepancy, we now send data required to draw the chart in the request itself so that chart always matches the data in the summary table. All these changes were made based on feedback from you. So keep sending your feature requests and feedback so that we can keep improving WinCache.


Hope this helps.