Hello. I recently detected an issue related to Memcached and Joomla. I have tested it with default Joomla application with just few test articles.
It turned out that using Memcached is increasing the CPU usage (CPU time) significantly. I have tested this with PHP 7 + memcached and PHP 5.6 + memcached. (Note: we are using memcached pecl and not memcache)
The case has been tested on a server at SiteGround. There are CPU time statistics there, where I was able to see the difference in the CPU time.
#### Steps to reproduce the issue & results
Enable Memcached by defining the following in the configuration.php file:
public $caching = '2';
public $cache_handler = 'file';
public $memcached_persist = '1';
public $memcached_compress = '0';
public $memcached_server_host = 'localhost';
public $memcached_server_port = '20044';
My Memcached process:
/usr/bin/memcached -d -p 20044 -u ivanyord -m 64 -c 256 -P /var/run/memcached/ivanyord/memcached-20044.pid -l 127.0.0.1
The Memcached seems to be working properly, as there were stats recorded in the "stats" (I am checking it via telnet to the memcached port)
In order to simulate access to my application, I have used "siege" from a remote server. This way, I have generated a little bit more than 2000 executions.
The results from the CPU time graph (when using PHP 7) are available in the screnshot: Screen Shot 2016-04-13 at 4.56.17 PM:
(The first column after the time is the Real CPU time)
The results from the CPU graph (when using PHP 5.6) are available in the screenshot: Screen Shot 2016-04-13 at 5.00.19 PM:
(The first column after the time is the Real CPU time)
Additionally, the requests from the siege are taking a lot more time to be processed whenever Memcached is enabled, compared to when Memcached is disabled:
HTTP/1.1 200 0.70 secs: 375 bytes ==> GET /jml1/index.php/component/search/?id=1&Itemid=101&format=opensearch
HTTP/1.1 200 2.73 secs: 3935 bytes ==> GET /jml1/
HTTP/1.1 200 2.87 secs: 3934 bytes ==> GET /jml1/
HTTP/1.1 200 2.97 secs: 3935 bytes ==> GET /jml1/
HTTP/1.1 200 3.14 secs: 3935 bytes ==> GET /jml1/
HTTP/1.1 200 3.28 secs: 3941 bytes ==> GET /jml1/index.php
HTTP/1.1 200 4.31 secs: 2834 bytes ==> GET /jml1/index.php/2-uncategorised/3-13f13f13f13
HTTP/1.1 200 4.89 secs: 3146 bytes ==> GET /jml1/index.php/component/users/?view=reset
HTTP/1.1 200 5.09 secs: 3283 bytes ==> GET /jml1/index.php/component/tags/tag/2-joomla
HTTP/1.1 200 2.81 secs: 3941 bytes ==> GET /jml1/index.php
HTTP/1.1 200 4.94 secs: 3146 bytes ==> GET /jml1/index.php/component/users/?view=reset
HTTP/1.1 200 0.39 secs: 3145 bytes ==> GET /jml1/index.php/component/users/?view=reset
HTTP/1.1 200 0.39 secs: 3931 bytes ==> GET /jml1/
HTTP/1.1 200 0.39 secs: 3282 bytes ==> GET /jml1/index.php/component/tags/tag/2-joomla
HTTP/1.1 200 0.39 secs: 3284 bytes ==> GET /jml1/index.php/component/tags/tag/2-joomla
HTTP/1.1 200 0.35 secs: 3371 bytes ==> GET /jml1/index.php/asdasdasdasd
HTTP/1.1 200 0.36 secs: 3931 bytes ==> GET /jml1/
HTTP/1.1 200 0.37 secs: 2931 bytes ==> GET /jml1/index.php/2-uncategorised/2-some-article
HTTP/1.1 200 0.48 secs: 375 bytes ==> GET /jml1/index.php/component/search/?id=1&Itemid=101&format=opensearch
HTTP/1.1 200 0.54 secs: 3371 bytes ==> GET /jml1/index.php/asdasdasdasd
CentOS
Joomla 3.5.1
PHP 5.6 and PHP 7
PHP info for PHP 5.6: http://ivan-yordanov.com/jml1/i.php
PHP info for PHP 7: http://ivan-yordanov.com/i.php
Apache 2.4
Nginx
MySQL 5.6
It seems that whenever Memcached is used, the process are getting significantly longer than when the Memcached is disabled. I would appreciate if you can provide some more information about why this occurs, as it seems that this happens with a default Joomla app.
Category | ⇒ | Cache |
All of the tests have been performed without Dynamic Caching, but I think that this should not be related to the case. The problem in this case is that enabling the Memcached is somehow making the processes longer and increases the CPU usage, with or without the other caching.
I am just trying to ensure that all external possibilities had been
eliminated
On 13 April 2016 at 15:29, Ivan Yordanov notifications@github.com wrote:
All of the tests have been performed without Dynamic Caching, but I think
that this should not be related to the case. The problem in this case is
that enabling the Memcached is somehow making the processes longer and
increases the CPU usage, with or without the other caching.—
You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#9898 (comment)
Brian Teeman
Co-founder Joomla! and OpenSourceMatters Inc.
http://brian.teeman.net/
Hi, @brianteeman There is no way for us to be absolutely 100% sure that this is a Joomla! issue but the tests indicate that Joomla! is slower when Memcached is used. We'll be happy to discuss the issue with someone who is familiar with the implementation of Memcached in Joomla! We can provide a test account if it is needed
Tried to ping you on skype via Daniel but I guess he is away from his desk ;)
Please check your configuration.php the values you have posted are for memcache not memcached - there are different variables for each. If you used joomla to make the settings then it should be fine but if you did it manually maybe you edited the wrong ones
So your own documentation needs updating as it is confusing memcache and memcached
https://www.siteground.co.uk/tutorials/supercacher/joomla_memcached.htm
Sorry, my fault. I have pasted the wrong code. I've fixed it now in the initial post. Actually, the test has been performed with the "memcached" variables and everything has been properly configured:)
As for the tutorial, we have updated it to look this way, as PHP 7 is using only the memcacheD class, so we need to provide instructions both for PHP 5.6 and below and PHP 7:) (PHP 5.6 contains both memcache and memcached classes)
Can you ping me on skype please - daniel has my contact
On 13 April 2016 at 15:47, Ivan Yordanov notifications@github.com wrote:
Sorry, my fault. I have pasted the wrong code. I've fixed it now in the
initial post. Actually, the test has been performed with the "memcached"
variables and everything has been properly configured:)As for the tutorial, we have updated it to look this way, as PHP 7 is
using only the memcacheD class, so we need to provide instructions both for
PHP 5.6 and below and PHP 7:) (PHP 5.6 contains both memcache and memcached
classes)—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#9898 (comment)
Brian Teeman
Co-founder Joomla! and OpenSourceMatters Inc.
http://brian.teeman.net/
Test results on my site on a different server but created by Ivan using the same tools which shows very similar results
@mbabker @wilsonge @roland-d any ideas
Status | New | ⇒ | Confirmed |
Build | master | ⇒ | 3.5.1 |
@brianteeman I am of very little help here I am afraid, I have no experience at all with memcached. The only thing I can think of is perhaps there is a stacktrace we can analyze. This would show where how much time is being consumed. If we have one with and one without memcached, we could perhaps see if there is anything in the code that is doing it.
I think that the Memcache/Memcached code has not been changed in 3.5.x and thus this issue is probably also present with older versions of Joomla!
Its beyond my area now but maybe this will help someone
http://lzone.de/cheat-sheet/memcached
I also faced the same problem with Memcache on Sitegroud - Cloud Server - PHP 5.6. Had to switch back to File Cache. I am not sure if it is a problem of Joomla or of Siteground. Lacking knowledge in Memcache system.
Unfortunately, applying the patches did not help. I have created a screenshot with the result after the changes - the results are the same..
screen shot 2016-04-18 at 07 25 03
Any other ideas?
What about turning off cache locking? There's no parameter controlling it so hacking these lines should do the trick (referencing the 3.5.1 release):
@mbabker Thanks for the suggestion. It seems that commenting these lines helps. Here are the results from the test, after the locking is disabled:
The results are identical. However, we will test this on a real site populated with data and extensions, as these tests are made on an empty, default application. I will let you know if anything else comes up.
@mbabker I haven't checked the code and I can only speculate why locking is needed. However, usually locking is needed when you have multiple processes updating the same data, and the wrong one ends up dating the cache. For example, when the cache expires you may have 5+ processes running the same SQL query to repopulate that cache. Using locking by default for all requests gets you on the safe side but at the same time performance in affected. So, my question is does locking need to be enabled by default and why? If it is disabled by default is critical data going to be affected (number of posts displayed per page for example is not critical data in my opinion). I believe locking should be disabled by default and enabled only for data that needs to be updated realtime. The problem is that right now probably there is no such definition and separation of data in Joomla! Which makes using Memcached a problem because it actually increases the CPU usage instead of reducing it which is the goal in the first place :)
I haven't the slightest clue what the locking mechanism is truly accomplishing but I know it gets into a while loop so if there are requests sitting there waiting for the loop to run through that would definitely cause spikes in resource usage.
I've been looking at other PHP caching libraries the last few days and I haven't seen any that implement a lock/unlock API like what exists now meaning either the library authors are intentionally keeping those libraries at a very high level or there's a valid argument for not using this type of lock mechanism. For reference places I've looked include Drupal, Symfony, Doctrine, and the php-cache package.
Thanks for the info @mbabker I am not an expert when it comes to caching but it looks to me that this specific part of the Cache subpackage should be reviewed and refactored if needed. Probably this should be also reviewed by other core Joomla! contributors.
On the first glance I would say problem is not in lock/unlock of individual items, but in driver implementation which is doing its own accounting - keys index. Problem is that to avoid corruption also index needs to be locked and since all threads need to wait until index lock is released to be able to add/remove item to/from index (there is only single index for all items/threads). Looks this was copied over from memcache driver where it was implemented as it was lacking something like getAllKeys function, which is necessary if you wish to get or delete all stored items (getAll(), gc() etc ).
Memcached has much better API so doing own accounting is not necessary any more http://php.net/manual/en/memcached.getallkeys.php - so for the start this driver needs to be refactored so it won't be using index anymore, which should fix above issue imho.
I would warn against total removal of lock/unlock (or alternative means) to prevent
https://en.wikipedia.org/wiki/Cache_stampede
http://davedevelopment.co.uk/2012/01/13/defending-against-cache-stampedes.html
Generic way to implement this prevention in JCache is as it is done in APC driver (add item with name key_lock to lock file ), but - there is a better function in memcached, that simplifies the process http://php.net/manual/en/memcached.cas.php - in other words, cas is a thread-safe set.
Simple usage example (without separate lock/unlock methods) http://blog.elijaa.org/2010/05/05/cas-command-pecl-memcached/ (better than example on http://php.net/manual/en/memcached.cas.php )
More advanced example memcached implementation similar to our lock/unlock ( doLock / doRelease ) https://github.com/feedbee/lock-manager/blob/master/Driver/Memcached.php
It would be great if you submitted a PR with changes
On 20 April 2016 at 22:33, Klas notifications@github.com wrote:
On the first glance I would say problem is not in lock/unlock of
individual items, but in driver implementation which is doing its own
accounting - keys index. Problem is that to avoid corruption also index
needs to be locked and since all threads need to wait until index lock is
released to be able to add/remove item form index (there is only single
index for all items/threads). Looks this was copied over from memcache
driver where it was implemented as it was lacking something like getAllKeys
function, which is necessary if you wish to get or delete all stored items
(getAll(), gc() etc ).
Memcached has much better API so doing own accounting is not necessary any
more http://php.net/manual/en/memcached.getallkeys.php - so for the start
this driver needs to be refactored so it won't be using index anymore,
which should fix above issue imho.I would warn against total removal of lock/unlock (or alternative means)
to prevent
https://en.wikipedia.org/wiki/Cache_stampedehttp://davedevelopment.co.uk/2012/01/13/defending-against-cache-stampedes.html
Generic way to implement this prevention in JCache is as it is done in APC
driver (add item with name key_lock to lock file ), but - there is a better
function in memcached, that simplifies the process
http://php.net/manual/en/memcached.cas.php - in other words, cas is a
thread-safe set.
Simple usage example (without separate lock/unlock methods)
http://blog.elijaa.org/2010/05/05/cas-command-pecl-memcached/ (better
than example on http://php.net/manual/en/memcached.cas.php )
More advanced example memcached implementation similar to our lock/unlock
( doLock / doRelease )
https://github.com/feedbee/lock-manager/blob/master/Driver/Memcached.php—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#9898 (comment)
Brian Teeman
Co-founder Joomla! and OpenSourceMatters Inc.
http://brian.teeman.net/
This might be a workaround with PHP 5, but still, the sites running on PHP 7 should use "memcached" and will have the issue present.
Yes, but current memcache and memcached storage class is very similar.
There is only a few difference in memcached.
When joomla members accept my pull for memcache then I or anybody can create the same structure for memcached.
Memcache/Memcached storage classes have the same weakness of indexing cache.
Q: Why memcache(-d) for big site (big cache) is slower than file cache?
A: Because of using one index table with objects(cache_id, size) and serialize/unserialize that index every time when you want to get/remove/set/clean cache. Unserialize eats performance!
IMHO Memcache changes should not be ported to memcached, index should be removed in memcached as it has this function built in. I'll make a PR
Yes, you have right.
i'm looking at this
@ivanyord are you able to reproduce the issue with the latest staging
@nibra take a look at it ;)
Status | Confirmed | ⇒ | Information Required |
set Status on "Information required".
@brianteeman Challenge accepted :)#16489
Status | Information Required | ⇒ | Closed |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2017-06-03 17:20:37 |
Closed_By | ⇒ | franz-wohlkoenig |
Set to "closed" on behalf of @franz-wohlkoenig by The JTracker Application at issues.joomla.org/joomla-cms/9898
closed as having PR #16489
I am assuming that you have disabled sitegrounds other caching mechanisms on this server
This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/9898.