Caching API response - performance

I am using onapp api in my website and in a page it is fetching all the servers in onapp. For some users this list is very large and it extends upto thousand in some cases. The response is not only data but it contains other information too. Also I am doing a pagination. So for each api has to be called and data should be populated. Now for increasing the speed of this I am writting the response to a file and reading from it. But it also taking time. Is there anyway to spped up this operation.
Before file caching, each page was taking around 45 seconds and now it is reduced to 25. But this is also a high value . I am using Symfony Framework. I am using the following code for caching data to file.
$userStatisticsCached=unserialize(file_get_contents($filePath));
if(is_null($userStatisticsCached)||$userStatisticsCached==false){
$userStatistics = $statisticsInstance->getList(1);
file_put_contents($filePath, serialize($userStatistics));
}
else {
$userStatistics=$userStatisticsCached;
}
Is there any better method for achieving the same output with less loading time ?

First: 45seconds is a lot to load a page. How many API calls are you making?
Second: Whoa, 25seconds when having all API calls already cached in filesystem is absolutely huge, too. How many filesystem lookups does your page load perform? Are you sure all your API requests are cached when measuring the 25s page load?
In-Memory Caching:
Depending on the size of your data, I would certainly suggest storing your cached data in memory to speed up cache lookups. For caches around 1GB or less it shouldn't be an issue (depending on what server hardware/hosting provider you are running on). An excellent first choice is Memcache, which also happens to have good PHP support.
Running Memcache: When working locally on your computer you should have no problem installing memcached for yourself. When you upload your website to the server, you'll either need to ensure that Memcache is running on the same server, or ask your server hosting provider for details on how to connect to their memcache server. Most PHP hosting providers offer Memcache as part of the hosting. If they don't, you can use a hosted remote memcache provider like MemCachier, although again the latency to a remote server is going to slow down your cache lookups.

Related

Laravel Redis Cache

I have a questions about Redis cache and laravel. By default laravel uses file which caches views to a file and load them from that cache.
Now here's the thing, I started using ElastiCache with Redis for my Laravel 5.4 project. If I change the driver to redis and it starts to cache (which I can tell by a loading time) but what does it actually cache? Does it automatically cache and retrieve my views? css? js? anything else?
I am also using redis for sessions driver, what does that give me?
Is it worth caching database as well? I was planning to cache whole database every hour and then whenever new item is added to database, add it to the existing cache. Is that possible?
The redis could give you two advantages:
faster data retrieving. Any memory-based cache system can give you this advantage than file-based or DB-based, such as memcached.
flexible data saving in redis. redis support many data-type store such as string, list, set, sorted-set and so on.
About caching what?
Cache the frequent request thing. If your client request something or query something to you, and you do not have cache, you will have to query it from your database, which give you an disk I/O time cost. And if the thing is heavy, then the IO cost will be bigger and slow down your server. So the smart way is , just query once and then save it into redis by suitable data-type store. After that retrive thousands with Cache. But you do not need to cache the overall database. It looks rude. And when you update something in db, just delete from your cache and after next time someone query this, it will save into cache again.
About Session. this is very frequent access thing for http server , so every user'session into cache is more light weight than file or db if your app server many many many people.
Cache the static file. Actually I has not dealt with this. But it can do this definitely! E.g. In modern architecture, there is often a Http server stand before your laravel such as nginx. In this way, you will use nginx serve the static file directly. And if you want decrease the disk io about this, you can add a module like redis2-nginx-module for nginx to do a same thing : save the static file into redis once and serve thousands.

What are the size limits for Laravel's file-based caching?

I am a new developer and am trying to implement Laravel's (5.1) caching facility to improve the speed of my app. I started out caching a large DB table that my app constantly references - but it got too large so I have backed away from that and am now 'forever' caching smaller chunks of data - for example, for each page only the portions of that large DB table that are relevant.
I have watched 'Caching Essentials' on Laracasts, done some Googling and had a search in this forum (and Laracasts') but I still have a couple of questions:
I am not totally clear on how the cache size limits work when you are using Laravel's file-based system - is there an overall in-app size limit for the cache or is one limited size-wise only per key and by your server size?
What are the signs you should switch from file-based caching to something like Memcached or Redis - and what are the benefits of using one of those services? Is it the fact that your caching is handled on a different server (thereby lightening the load on your own)? Do you switch over to one of these services when your local, file-based cache gets too big for your server?
My app utilizes several tables that have 3,000-4,000 rows - the data in these tables is constantly referenced and will remain static unless I decide to add new options. I am basically looking for the best way to speed up queries to the data in these tables.
Thanks!
I don't think Laravel imposes any limitations on its file i/o at all - the limitations will be with how much what PHP can read / write to a file at once, or hold in its memory / process at any one time.
It does serialise the data that you cache, and unserialise it when you reload it, so your PHP environment would have to be able to process the entire cache file (which is equivalent to the top level cache key) at once. So, if you are getting cacheduser.firstname, it would have to load the whole cacheduser key from the file, unserialise it, then get the firstname key from that.
I would take the PHP memory limit (classic, i know!) as a first point to investigate if you want to keep down this road.
Caching services like Redis or memcached are bespoke, optimised caching solutions. They take some of the logic and responsibility out of your PHP environment.
They can, for example, retrieve sub-keys from items without having to process the whole thing, so can retrieve part of some cached data in a memory efficient way. So, when you request cacheduser.firstname from redis, it just returns you the firstname attribute.
They have other advantages regarding tagging / clearing out subsets of caches (see [the cache tags Laravel docs] (https://laravel.com/docs/5.4/cache#cache-tags))
Another thing to think about is scaling. If your site is large enough, and is load-balanced across multiple servers, the filesystem caching may be different across those servers, as each server can only check their local filesystem for the cache files. A caching service can be on a different server (many hosts will have a separate redis / memcached services available), so isn't victim to this issue.
Also - as I understand it (and this might be the most important thing), the file cache driver in Laravel is mainly for local development and testing. Although it can work fine for simple applications with basic caching needs, it's not intended for large scalable production environments.
Personally, I develop locally and test with file caching, as i'm only dealing with small amounts of data then, and use redis to cache on production environments.
It doesn't necessarily need to be on a separate server to get the benefits. If you are never going to scale to multiple application servers, then using a caching service on the same server will already be a large improvement to caching large documents.

Performance difference between Azure Redis cache and In-role cache for outputcaching

We are moving an asp.net site to Azure Web Role and Azure Sql Database. The site is using output cache and normal Cache[xxx] (i.e. HttpRuntime.Cache). These are now stored in the classic way in the web role instance memory.
The low hanging fruit is to first start using a distributed cache for output caching. I can use in-role cache, either as co-located or with a dedicated cache role, or Redis cache. Both have outputcache providers ready made.
Are there any performance differences between the two (thee with co-located/dedicated) cache methods?
One thing to consider is that will getting the page from Redis for every pageload on every server be faster or slower than composing the page from scratch one every server every 120 seconds but inbetween just getting it from local memory?
Which will scale better when we want to start caching our own data (i.e. pocos) in a distributed cache instead of HttpRuntime.Cache?
-Mathias
Answering to your each question individually:
Are there any performance differences between the two (thee with
co-located/dedicated) cache methods?
Definately co-located caching solution is faster than dedicated cache server, as in co-located/inproc solution request will be handled locally within the process where as dedicated cache solution will involve getting data over the network. However since data will be in-memory on cache server, getting will still be faster than getting from DB.
One thing to consider is that will getting the page from Redis for
every pageload on every server be faster or slower than composing the
page from scratch one every server every 120 seconds but inbetween
just getting it from local memory?
It will depend on number of objects on page i.e. time taken to compose the page from scratch. Though getting from cache will involve network trip time but its mostly in fractions of a millisecond.
Which will scale better when we want to start caching our own data
(i.e. pocos) in a distributed cache instead of HttpRuntime.Cache?
Since HttpRuntime.Cache is in-process caching, it is limited to single process's memory therefore it is not scalable. A distributed cache on the other hand is a scalable solution where you can always add more servers to increase cache space and throughput. Also out-proc nature of distributed cache solution makes it possible to access data cached by on application process to be used by any other process.
You can also look into NCache for Azure as a distributed caching solution. NCache is a native .Net distributed caching solution.
Following blog posts by Iqbal Khan will help you better understand the need of distributed cache for ASP.Net applications:
Improve ASP.NET Performance in Microsoft Azure with Output Cache
How to use a Distributed Cache for ASP.NET Output Cache
I hope this helps :-)
-Sameer

Sqlite as cache store to store static copies of dynamic pages - Is it a good idea?

We're running our blog from a shared hosting account. Our host limits the allowed inodes/number of files on the hosting account to 150,000. We've implemented our caching mechanism that caches all pages in full as soon as they are accessed so that subsequent seeks are delivered from cache. Unfortunately, the inode limit won't allow us to store more pages very soon.
Fortunately we have sqlite on our server. Though we have mysql too, but our shared hosting account only allows us to have maximum 25 concurrent connections from the apache webserver to the mysql server. That's a major constraint! Its said that sqlite is "serverless", and so I believe sqlite won't have that kind of limitation.
With that, should I and can I use a sqlite table to store full cache pages of all dynamic pages of our blog ? The average cached page size is around 125 kbs and I have around 125,000 cache pages and growing.
Will that have any kind of bottlenecks to slow down the cache page delivery out of the sqlite database file?
Will I be able to write more pages to the cache_table in the sqlite database while simuntaneously deliverying sought pages from the cache_table to the site visitors?
I't not a good idea cause sqlite usage may impact you website performance (at least on response time).
I recommend to use Memcached or NoSQL DB as a last resort (need to test for response time rise).
But if you have not choise, sqlite will be better then MySQL, cause its select operations are faster.
Haven't calculated that because there has never been a need to calculate max page generation time. I manage all pages statically in full, and with that, it has always been a stable process without any trouble.
Our server load varies from 400 to 8000 page requests in an hour.

Caching with multiple server

I'm building an application with multiple server involved. (4 servers where each one has a database and a webserver. 1 master database and 3 slaves + one load balancer)
There is several approach to enable caching. Right now it's fairly simple and not efficient at all.
All the caching is done on an NFS partition share between all servers. NFS is the bottleneck in the architecture.
I have several ideas implement
caching. It can be done on a server
level (local file system) but the
problem is to invalidate a cache
file when the content has been
update on all server : It can be
done by having a small cache
lifetime (not efficient because the
cache will be refresh sooner that it
should be most of the time)
It can also be done by a messaging
sytem (XMPP for example) where each
server communicate with each other.
The server responsible for the
invalidation of the cache send a
request to all the other to let them
know that the cache has been
invalidated. Latency is probably
bigger (take more time for everybody
to know that the cache has been
invalidated) but my application
doesn't require atomic cache
invalidation.
Third approach is to use a cloud
system to store the cache (like
CouchDB) but I have no idea of the
performance for this one. Is it
faster than using a SQL database?
I planned to use Zend Framework but I don't think it's really relevant (except that some package probably exists in other Framework to deal with XMPP, CouchDB)
Requirements: Persistent cache (if a server restart, the cache shouldn't be lost to avoid bringing down the server while re-creating the cache)
http://www.danga.com/memcached/
Memcached covers most of the requirements you lay out - message-based read, commit and invalidation. High availability and high speed, but very little atomic reliability (sacrificed for performance).
(Also, memcached powers things like YouTube, Wikipedia, Facebook, so I think it can be fairly well-established that organizations with the time, money and talent to seriously evaluate many distributed caching options settle with memcached!)
Edit (in response to comment)
The idea of a cache is for it to be relatively transitory compared to your backing store. If you need to persist the cache data long-term, I recommend looking at either (a) denormalizing your data tier to get more performance, or (b) adding a middle-tier database server that stores high-volume data in straight key-value-pair tables, or something closely approximating that.
In defence of memcached as a cache store, if you want high peformance with low impact of a server reboot, why not just have 4 memcached servers? Or 8? Each 'reboot' would have correspondingly less effect on the database server.
I think I found a relatively good solution.
I use Zend_Cache to store locally each cache file.
I've created a small daemon based on nanoserver which manage cache files locally too.
When one server create/modify/delete a cache file locally, it send the same action to all server through the daemon which do the same action.
That mean I have local caching files and remote actions at the same time.
Probably not perfect, but should work for now.
CouchDB was too slow and NFS is not reliable enough.

Resources