Will caching be appropriate for this scenario? - php

So I have a PHP CodeIgniter webapp and am trying to decide whether to incorporate caching.
Please bear with me on this one, since I'll happily admit I don't fully understand caching!
So the first user loads up a page of user submitted-content. It takes 0.8 seconds (processing) to load it 'slow'. The next user then loads up that same page, it takes 0.1 seconds to load it 'fast' from cache.
The third user loads it up, also taking 0.1 seconds execution time. This user decides to comment on the page.
The fourth user loads it up 2 minutes later but doesn't see the third user's comment, because there's still another 50 minutes left before the cache expires
What do you do in this situation? Is it worth incorporating caching on pages like this?
The reason I'd like to use caching is because I ran some tests. Without caching, my page took an average of 0.7864 seconds execution time. With caching, it took an average of 0.0138 seconds. That's an improvement of 5599%!
I understand it's still only a matter of milliseconds, but even so...
Jack

You want a better cache.
Typically, you should never reach your cache's timeout. Instead, some user-driven action will invalidate the cache.
So if you have a scenario like this:
Joe loads the page for the first time (ever). There is no cache, so it takes a while, but the result is cached along the way.
Mary loads the page, and it loads quickly, from the cache.
Mary adds a comment. The comment is added to the database (or whatever), and the software invalidates the cache
Pete comes along and loads the page, the cache is invalid, so it takes a second to render the page, and the result is cached (as a valid cache entry)
Sam comes along, page loads fast
Jenny comes along, page loads fast.
I'm not a CodeIgniter guy, so I'm not sure what that framework will do for you, but the above is generally what should happen. Your application should have enough smarts built-in to invalidate cache entries when data gets written that requires cache invalidation.

Try CI's query caching instead. The page is still rendered every time but the DB results are cached... and they can be deleted using native CI functionality (i.e no third party libraries).

While CI offers only page level caching, without invalidation I used to handle this issue somewhat differently. The simplest way to handle this problem was to load all the heavy content from the cache, while the comments where loaded via a non cacheable Ajax calls.
Or you might look into custom plugins which solve this, like the one you pointed out earlier.
It all comes down to the granularity at which you want to control the cache. For simple things like blogs, loading comments via external ajax calls (on demand - as in user explicitly requests the comments) is the best approach.

Related

Magento + Varnish + Memcache: session_start() is very slow

we run a Magento shop with Varnish. Everything works fine except the following problem: If you open a shop page and then leave the browser open for a very long time, say 12 - 24 hours, and then reload the page, the page loads very slow (about 15s).
We located the problem in the start_session() call in app/code/core/Mage/Core/Model/Session/Abstract.php. This call takes about 15s.
We use memcache (not memcached) for session management.
We googled a lot, and found many posts about slow session starts, but none about this particular issue.
Can anobody help?
Many thanks in advance,
Tilman
I've seen this quite a lot on New Relic as well.
From what I've seen there are a few different causes, I don't have a complete understanding of this issue but it is something I've been looking into recently. Here's my findings.
Sessions in Magento, Locking, and New Relic
Every controller action in Magento uses the session, whether it needs to or not. The session is eagerly instantiated in Mage_Core_Controller_Varien_Action::preDispatch
If you have session locking enabled, this means that for the duration of the request your session is locked down until the request completes. I haven't found the bit of code that releases the session lock yet, but I'm pretty sure it's in there somewhere.
Ultimately this means if you fire off multiple concurrent requests to Magento controller actions from the one location using the same session, you will have to wait for some of those requests to complete and unlock the session to proceed. I usually see this as a slow transaction on new relic stuck at Mage_Core_Model_Session_Abstract_Varien::start for ~30 seconds (my session lock wait timeout I think).
This report on New Relic has multiple downsides as I see it
Slows down the total average response time, because these requests are slower than they otherwise should have been.
New Relic records a sample of the slowest transactions, if I have performance bottlenecks that take for example 20 seconds New Relic will not report them automatically for me if the same URL is plagued by session locking timeouts. The timeouts are hiding the useful data.
Causes
I've seen a few common causes for this, not a definitive list by any means
Bots
Crawlers like Baidu and Yandex being a being a bit rude and battering the website. They're being run from one location firing off numerous requests, using the same session, and tripping up the session locking mechanism, hence showing slow transactions in New Relic.
Ajax calls to Magento controller actions
With varnished websites customer specific data must be loaded with care, some websites manage this by using ajax calls to the Magento backend to get the required data. I have also seen some websites using ajax calls to the backend to get product specific information, such as the amount left in stock when an item is on sale.
If a single page triggers multiple ajax calls to the backend on page load, it can potentially trigger the session locking mechanism. The more ajax calls back to the Magento backend the more likely you are to experience locking.
Varnish ESI
The same as above really, except instead of using ajax calls it uses Edge Side Includes which seem to be new calls to the backend.
My Plan
I have not actioned this yet so it's still purely theoretical, but it's something i'm looking into doing over the next few months.
I brought this problem up during the Mage Titans UK 2016 conference and Fabrizio Branca pointed me towards the following module: https://github.com/AOEpeople/Aoe_BlackHoleSession.
Based on a regular expression the module will prevent Bots from creating real sessions, this should have the benefit that no session lock will be hit, and that your session resources won't be battered by rude bots. Bots should no longer pollute your New Relic readings.
For ajax/ESI calls to get customer data there on cached pages there's nothing you can do that I can see. You need access to the session in order to retrieve customer specific data.
However, for ajax/ESI calls to get catalog specific data (such as limited stock) I don't see any need for a session to exist on that request at all. My plan for the future is to trial out an extension to the Aoe_BlackHoleSession module so that I can silo off requests to a specific URL as being sessionless.
I'm less familiar with the internals of ESI, so sadly I don't have too much to comment there.
An alternative
During the conference Fabrizio Branca said he was able to disable session locking completely without any ill effects, test at your own risk.

Codeigniter page cache not considering inputs?

How can I get CodeIgniter page cache to take inputs into account? For example, say I have a pagination system. With cache enabled, if I go to page 1, then page 2 (same controller)... CI cache will return page 1's content.
function my_controller() {
$this->output->cache(1);
$page = $this->input->post("page");
$data = getData($page);
$this->load->view('my_view', $data);
}
In the above example, you cannot pan through pages correctly. It will keep loading the cached page even if the posted input changes.
How can I get the cache system to take $_POST data into account and treat those as different requests from a cache point of view?
Caching dynamic content where the view has no noticeable change to the caching class can get messy...
The simplest solution is don't cache dynamic pages, its not really what caching is for anyway, caching is meant for (at least, mostly) static data.
Another way you can do it (depending on result sets) is to use javascript and paginate client side, and use ajax calls to fetch the data from the server, the client would never actually leave the single view and only the initial view would be cached.
How often does the content change? are we talking like a list of orders that changes minute by minute, or a list of products that changes maybe monthly?
If loaded by ajax then just make sure what you are calling is not exposed to your cache (unless the content rarely changes)... As it would be called from a different method this is not difficult to ensure, and on page load you would have it call the first xx number of results fresh every time, but using the benefits of caching for the rest of the view.

What does "Refresh cache" mean in Magento?

Here is what I found after investigating cache behavior in Magento.
I'm not sure of this and asking for correction.
When something like a product is modified, cache entries such as "HTML Block" becomes "invalidated", resulting on being ignored and not used in frontend. This makes sense because these data is now outdated.
It remains "invalidated" until manually "refreshed" through admin area.
Once manually "refreshed", the first render of a cached block will construct its cached copy and append it to this HTML Block cache reserve. Subsequent render operation of this block will find this cache usable, and use it, finally, until cache becomes "invalidated" over again.
Why this process is called "refresh", as it should be something like "reset"? because "refresh" would means it generate updated cache snapshot, but instead it merely allows cache entries to be constructed.
Why don't invalidated data become refreshed once it's invalidated?
This makes me question my conclusion, was I correct?
why this process is called "refresh", as it should be like "reset"
Your general take on this is correct -- some people call it "refresh" because although the action you take resets the cache, in a working Magento system the cache will almost immediately rebuild itself the next time you (or another user) loads the page.
Why don't invalidated data become refreshed once it's invalidated?
When the cache is invalidated, that means the developer working on whatever backend feature invalidated the cache was smart enough to know their actions required a cache refresh, but that that programatic cache control wasn't sufficient to refresh only their portion of the changed cache.
For example, certain blocks might render a change in a product's price, which means any blocks with the price cached need to be refreshed. However, as a backend programmer, there's no way to know which blocks need that invalidation, nor know which cache system (block cache, FPC, varnish) they're stored in. There's also a question of store performance -- if you're editing 100 products, do you want Magento to rebuild the cache 100 times during peak traffic hours? So, instead of deciding how to handle all that, the developer marks the cache as invalidated. This allows the cache system to take whatever action it deems necessary.
In a perfect theoretical cache system, there would be automated processes running that would detect an invalidated cache, and know what to do and when to refresh it. That's a complex system to implement and maintain, so instead Magento chose to simply notify the store owner's of the invalidated cache, and let them take whatever action they deemed appropriate.
Magento cache refreshing should happen when data important to the user is modified by default. E.g. order data, shipping info etc.
This is the behavior I observed during my years writing extensions for the software. You can can manually disable this behavior, but as it stands by default , dynamic data should be punching "holes" through the cache.

PHP page process separation

If some php page is running some long process such as sleep or while loop that makes it take a while till it loads, does it affect on other processes from the same page ?,
I noticed when i try to open the same page with different short process, it also takes so long to load and to be clear it doesn't load before the first one (long process) does,
is it true or something's wrong with my code and how to prevent it ?
i think it has something to do with cache, i don't wanna mess up though before getting a tip or an answer
PHP run in a single process, each time you access the page, it start the process, process, and finish.
Each process won't affect the others.
I noticed when i try to open the same page with different short
process, [...] it doesn't load before the first one (long process) does
The most common reasons:
Your scripts use PHP sessions "as is", which use file locking. The file locking mechanism ensures only one script at a time can edit the session data of each user, but this does mean that provided two requests from the same user happen simultaneously, a second script will not start before the first has finished if they both rely on sessions (two different users have different session files though, so they can't collide)
The browser automatically detects the page is taking long and delays subsequent requests intentionally in the background — I believe this is something Google Chrome does by default.
Both cases are relatively safe however, because the delay is only present in case the same user is trying to load several pages simultaneously which is not usual — different users will not see delays regardless how long the actual page takes to load.
More on the topic in this excellent SO answer.

How does CodeIgniter output caching work?

I read this link :-
http://codeigniter.com/user_guide/general/caching.html
It is written that :-
When a page is loaded for the first time, the cache file will be written to your system/cache folder
and that we can cache a view by $this->output->cache(60);. But how does it actually work? What if regularly my users keep updating and deleting records as a result of which view changes very often. Will it show the modified data? or will the cache bring back the old stale data? (before inserts and updates)? If it automatically manages and brings fresh data from the database, then what is purpose of specifying the minutes in cache function?
Thanks in advance :)
The way codeigniter's caching works generally is this:
A page request is made. Codeigniter (before very much of the framework has even been loaded) does a hash of the current url and if it finds that filename in the cache directory, it serves that.
The only way you can get fresh data is to manually delete the files. When codeigniter doesn't find the file from the hash it generated, it dynamically creates the page.
Codeigniter's implementation is called "full page" caching, and as so, is limited in it's usefullness. There's a partial caching library I've looked into from Phil Sturgeon here: http://philsturgeon.co.uk/code/codeigniter-cache
Honestly, for most projects, full page caching really isn't all that useful. In fact, the projects that I need full page caching I don't even leave that up to codeigniter (I leave it to the webserver: it's way faster).
I'd guess what you're looking for is a partial caching method; most people would prefer this. Look into APC if you're using a single server or Memcached if you have multiple servers.
Good Luck.
But how does it actually work?
If a cached version exists that is younger than the cache time, that cached version will be outputted.
Will it show the modified data?
Eventually yes, but with a lag of $cache_time
What if regularly my users keep updating and deleting records as a result of which view changes very often.
Reduce the cache time or don't use caching at all

Categories