php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58754 apc strange behaviour with php files cached from tmpfs
Submitted: 2009-07-06 14:56 UTC Modified: 2016-08-31 15:13 UTC
From: tdevelioglu at ebuddy dot com Assigned: cmb (profile)
Status: Wont fix Package: APC (PECL)
PHP Version: 5.2.6 OS: Debian Linux 5.0 (x86_64)
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please — but make sure to vote on the bug!
Your email address:
MUST BE VALID
Solve the problem:
33 + 21 = ?
Subscribe to this entry?

 
 [2009-07-06 14:56 UTC] tdevelioglu at ebuddy dot com
Description:
------------
On Debian 5.0, x86-64.
Kernel version 2.6.29.4

apc.ini:

extension=apc.so
apc.shm_size=64
apc.max_file_size=2M

We have a php web application in which apc exhibits, to me, strange behavior in the following two situations:

The situations are identical, except for the details below.

A) PHP application creates and updates temporary php files in a folder 'A' on an ext3 filesystem.

B) Same application creates and updates these temporary php files on a tmpfs volume 'B'.

(simply put, we change the location of the temporary php files from ext3 fs on disk to tmpfs)

The temporary php files are used via 'include' by the application during runtime.

With (files on ext3) 'A':

- No multiple entries per file exist in cache.
- Cache never grows beyond 30M.
- Low overall fragmentation (< 4%)

With (files on tmpfs) 'B':

- Many multiple entries per file over time in cache. (same files are added over and over as they are modified)
- Cache grows up to the max shm size (64M) and is flushed.
- No fragmentation

With tmpfs each time a php file is updated it gets cached to a new slot. No fragmentation occurs because probably it is appended to the end of the allocated shm space, cache slots are never replaced.
So the cache keeps on growing infinately.

To me this is strange behavior, as I would expect apc to behave equally when dealing with php files read from an ext3 filesystem and php files read from tmpfs.



Reproduce code:
---------------
This regards open-source application 'OpenX' ad server, available at http://www.openx.org/.

Can be reproduced by changing the storage location of the delivery cache to a tmpfs mount.

Expected result:
----------------
Identical results from apc when dealing with php files cached from a tmpfs store and php files cached from an ext3 filesystem.

Actual result:
--------------
Updated php files on tmpfs are cached into new slots endlessly, filling up the cache with obsolete (old) entries of the same file.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-07-06 14:58 UTC] tdevelioglu at ebuddy dot com
edited for better clarity
 [2009-07-06 15:06 UTC] tdevelioglu at ebuddy dot com
Could have sworn I filled in the apc version in the report form, but here it is again:

apc version 3.0.19 (debian package version 3.0.19-2)
 [2009-07-07 17:48 UTC] gopalv82 at yahoo dot com
Actually, the behaviour described is as APC should work.

For every file which is updated or new, a new slot is 
indeed created and the new/updated file inserted into its 
own new slot.

Now, I have *no* idea why it doesn't do that for ext3. 

Plus, just for fun ... what does the inode# of the tmpfs 
files say (versus the ext3).

stat -c "%n - %d:%i" tmpfs/foo 

In a loop in the command line should give enough information about it. 

If indeed updating a file in ext3 leaves the inode# of a 
file unchanged, I need to know about it ... like NOW.

APC caches using device+inode as the key for the cache 
(and therefore to determine the slot it belongs to).

I'll run a bit of stuff on tmpfs here, but get back to me
with the inode stuff.
 [2009-07-08 06:22 UTC] tdevelioglu at ebuddy dot com
first, I've omitted an important detail:

The ext3 fs in question is mounted with the ext4 driver. It has none of the features of ext4 enabled, so it is still a pure ext3 fs but it could have to do with the inode#'s not changing.

second, I have done as you asked:

while true;do stat -c "%n - %d:%i" *;sleep 1200;done > /home/taylan/stat.log

---- tmpfs:

The inode#'s are unique (there are some duplicates but it's possible those files haven't updated in 20mins):

copenhagen:/home/taylan# sort stat.log|uniq -c

      1 deliverycache_f24f1772cfb16e49e00e0837d85c563e.php - 15:32384580
      1 deliverycache_f24f1772cfb16e49e00e0837d85c563e.php - 15:32553966
      1 deliverycache_f24f1772cfb16e49e00e0837d85c563e.php - 15:32737399
      1 deliverycache_f2f232461a6daa6744f51bde7bdc0907.php - 15:32385517
      1 deliverycache_f2f232461a6daa6744f51bde7bdc0907.php - 15:32553387
      1 deliverycache_f2f232461a6daa6744f51bde7bdc0907.php - 15:32730477
      1 deliverycache_f64676fa920036f8f0ea35b7ccb23b4f.php - 15:32384922
      1 deliverycache_f64676fa920036f8f0ea35b7ccb23b4f.php - 15:32555244
      1 deliverycache_f64676fa920036f8f0ea35b7ccb23b4f.php - 15:32732425
      1 deliverycache_f931e305520239c4ebb5830a77410610.php - 15:32387326
      1 deliverycache_f931e305520239c4ebb5830a77410610.php - 15:32557744
      1 deliverycache_f931e305520239c4ebb5830a77410610.php - 15:32735017
      1 deliverycache_f9c4b2ca527f056504e9ffd835d596ea.php - 15:32385008
      1 deliverycache_f9c4b2ca527f056504e9ffd835d596ea.php - 15:32484272
      1 deliverycache_f9c4b2ca527f056504e9ffd835d596ea.php - 15:32669152
      1 deliverycache_f9e4b0ad13b7223daa560ae916c929d7.php - 15:32384729
      1 deliverycache_f9e4b0ad13b7223daa560ae916c929d7.php - 15:32553433
      1 deliverycache_f9e4b0ad13b7223daa560ae916c929d7.php - 15:32733604
      1 deliverycache_fcc46b61f71bc7309d8ed1f9764ca0f1.php - 15:32386537
      1 deliverycache_fcc46b61f71bc7309d8ed1f9764ca0f1.php - 15:32558195
      1 deliverycache_fcc46b61f71bc7309d8ed1f9764ca0f1.php - 15:32738633
      1 deliverycache_fd9aa6baf31e10f8354071c3b9ba7215.php - 15:32396026
      1 deliverycache_fd9aa6baf31e10f8354071c3b9ba7215.php - 15:32477375
      1 deliverycache_fd9aa6baf31e10f8354071c3b9ba7215.php - 15:32673734
      1 deliverycache_fe93d383915eab6f300944b4e669b958.php - 15:32384859
      1 deliverycache_fe93d383915eab6f300944b4e669b958.php - 15:32555399
      1 deliverycache_fe93d383915eab6f300944b4e669b958.php - 15:32732354
      1 deliverycache_fefb4d2219474b63636884be8e1e3575.php - 15:32387794
      1 deliverycache_fefb4d2219474b63636884be8e1e3575.php - 15:32557847
      1 deliverycache_fefb4d2219474b63636884be8e1e3575.php - 15:32736366
      1 deliverycache_ffe16b14e6a7065bbc7c9991b6025d03.php - 15:32385666
      1 deliverycache_ffe16b14e6a7065bbc7c9991b6025d03.php - 15:32562047
      1 deliverycache_ffe16b14e6a7065bbc7c9991b6025d03.php - 15:32744477

---- ext3 mounted as ext4:
Looks like the inode#'s are not changing.
Some files have their inode#'s changed, but most of them not. (could be the file is deleted and recreated by the app)

copenhagen:/home/taylan# sort stat.log|uniq -c

      4 deliverycache_ea38c03425806a4cfa89b17b53bf892b.php - 2049:5180886
      4 deliverycache_eb9287f12a1314aa4f7280bac5a22d58.php - 2049:5180945
      4 deliverycache_ecc50aad499684719f55760d91b8997e.php - 2049:5180939
      4 deliverycache_ed0aa921d5b5dd6919f48b232124989b.php - 2049:5178041
      4 deliverycache_ef7be52f446a5f0f76415d5e996f7d20.php - 2049:5180816
      2 deliverycache_ef99e5fb5900e4914991a798609ca479.php - 2049:5180801
      2 deliverycache_ef99e5fb5900e4914991a798609ca479.php - 2049:5180826
      4 deliverycache_f06f98113a46e6e82c820c938727eadd.php - 2049:5180785
      4 deliverycache_f1255584e4ae55e126cb85e40fec8794.php - 2049:5178015
      4 deliverycache_f24f1772cfb16e49e00e0837d85c563e.php - 2049:5178097
      2 deliverycache_f2f232461a6daa6744f51bde7bdc0907.php - 2049:5180777
      2 deliverycache_f2f232461a6daa6744f51bde7bdc0907.php - 2049:5180782
      4 deliverycache_f64676fa920036f8f0ea35b7ccb23b4f.php - 2049:5178071
      4 deliverycache_f931e305520239c4ebb5830a77410610.php - 2049:5180859
      4 deliverycache_f9c4b2ca527f056504e9ffd835d596ea.php - 2049:5180793
      4 deliverycache_f9e4b0ad13b7223daa560ae916c929d7.php - 2049:5178028
      4 deliverycache_fcc46b61f71bc7309d8ed1f9764ca0f1.php - 2049:5178101
      4 deliverycache_fd9aa6baf31e10f8354071c3b9ba7215.php - 2049:5180946
      4 deliverycache_fe93d383915eab6f300944b4e669b958.php - 2049:5178111
      3 deliverycache_fefb4d2219474b63636884be8e1e3575.php - 2049:5180989
      4 deliverycache_ffe16b14e6a7065bbc7c9991b6025d03.php - 2049:5180857

----

With an ext3 fs mounted as ext4 the inode# of a file does not change after an update.

----

I'm going to mount ext3 as ext3 to see whether the behavior is exclusive to ext4.
 [2009-07-08 09:11 UTC] tdevelioglu at ebuddy dot com
ext3 mounted as ext3 leads to the same results.

stat -c "%y %n - %d:%i":

2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:39:02.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:59:23.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913
2009-07-08 14:59:23.000000000 +0200 deliverycache_e7815349d09ed843eb24e76eb87d5c69.php - 2049:5180913

Inode# stays the same after the file is modified.
 [2009-10-11 04:45 UTC] shire@php.net
Sounds like with the inodes changing on every file update the cache doesn't find the original entries in the cache (as they are key'd off of the inode #) and remove them on the new insert, so entries just stack up.  

Do you have a ttl set for your file cache?  If not does setting one to a very low setting help? (entries will be removed if we come across them or on a cache full scenario, rather than expunging the entire cache).

Another option here would be to upgrade to 3.1.1 or above, and use the apc_delete_file($filename) before you delete the original file on disk.  Another similar option would be to set apc.stat=0 and then use apc_compile_file() to update the entries manually after you update the files on disk.  The LFU in APC-4.0.0 will expunge these entries more efficiently, but that's not really ideal memory usage either.  Perhaps the proper fix here is to allow some combination of full paths but with stats as well as none of the above suggestions is really ideal.
 [2016-08-31 15:13 UTC] cmb@php.net
-Status: Open +Status: Wont fix -Assigned To: +Assigned To: cmb
 [2016-08-31 15:13 UTC] cmb@php.net
According to <https://bugs.php.net/69618>, APC support has been
discontinued in favor of OPcache, APCu, the session upload
progress API and WinCache. Therefore this issue won't get fixed.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Mar 29 05:01:28 2024 UTC