I'm having a strange problem in my application (Yii Framework 1.1.8).
I called a function as follows:
UserDataModel::model()->cache(3600, $dependency)->getAttributes();
After calling this function I called another model and fetched the data.
ProfileModel::model()->findAll();
To my surprise, ProfileModel was also cached. When I remove the first line (UserDataModel), the ProfileModel fetches the uncached data. Since both models are different, why first model is forcing cache for the next model call ?
Is there anything wrong with my implementation ?
Thanks.
Arfeen
I hope I can help you out, as I can see you are not specifying the third parameter in the cache which indicates the number of queries to be cached. My guess is that if the dependency is true, everything from that line on to the bottom will be cached in the cfilecache created totally independent to the model. In fact I have cache which implements dependency on several tables so I can cache more than one query and in the third parameter I tell the cache how many queries will I save
Related
I've got a script that fetches data from a database using doctrine. Sometimes it needs to fetch the data for the same entity, the second time however it uses the identity map and therefor might go out of sync with the database (another process can modify the entities in the db). One solution that we tried was to set the query hint Query::HINT_REFRESH before we run the DQL query. We however would like to use it also with simple findBy(..) calls but that doesn't seem to work? We would also like to be able to set it globally per process so that all the doctrine SELECT queries that are run in that context would actually fetch the entities from the DB. We tried to set the $em->getConfiguration()->setDefaultQueryHint(Query::HINT_REFRESH, true); but again that doesn't seem to work?
Doctrine explicitly warns you that it is not meant to be used without a cache.
However if want to ignore this, then Cerad's comment (also mentioned in in this answer) sound right. If you want to do it on every query though you might look into hooking into a doctrine event, unfortunately there is no event for preLoad, only postLoad, but if you really don't care about performance you could create a postLoad listener which first gets the class and id of the loaded entity, calls clear on the entity manager and finally reloads it. Sounds very wrong to me though, I wash my hands of it :-)
I know you can cache a query by appending ->remember($minutes).
However, this doesn't work when using loading on an existing Eloquent result. This is because load doesn't return a querybuilder but directly executes it.
Say you want to load the friends of a user:
$user=Auth::user();
$user->load('friends'); // How to cache these results ?
How can I cache these ?
You can't using this code on its own. You do have two options, though:
1) Wrap your code in a wrapper somewhere (essentially abstracting away this call), which does a cache check first, and runs these queries if the cached item does not exist or is expired.
2) Extend the Auth library, specifically its EloquentUserProvider class, and modify the query performed by the retrieveById() method.
You can see one method of abstracting methods and caching in Chris Fidao's Implementing Laravel. The accompanying book is handy!
You have to convert User object into QueryBuilder to get access to ->remember() method
Try
User::with('friends')->where('id', Auth::user()->id)->remember()->first();
I am using CodeIgniter and doctrine for my project. When I enabled CodeIgniter profiling I got know My one request is taking 18MB of memory. I created test project with simple CI and Doctrine libraries. On test project CRUD operation takes 6 to 7 MB memory per request. After digging into to application I got to know included models are taking too much memory.
Earlier I loaded model into constructor method. But it consumes too much memory.
I decided to load models into every method which are required to particular method.
Is that good approach?
Please give me suggestions.
No you should not load model in every method. instead try load the model in contructor of each controller file. Hope you understand my answer.
Definitely, we should load models conditionally.
1) You should write certain conditions in the construction function for loading models.
2) Also, only required/dependent models should be included in any controller.
3) Including model in every method load the page faster. But, its not the best practice.
4) Rather you should dig into your model codes and find out why do its taking this much amount of time to load.
Your approach is right.
Use autoload.php to load models its makes to fully utilize the frameworks benefits
I moved from an old sever running centOS on a managed hoster to a new one running Ubuntu in AWS.
Post the move I've noticed that the page that loads a list of items is now taking ~10-12 secs to render (sometimes even up to 74secs). This was never noticed on the old server. I used newrelic to look at what was taking so long and found that the sfPHPView->render() was taking 99% of the time. From nerelic there is approximately ~500 calls to the DB to render the page.
The page is a list of ideas, with each idea a row. I use the $idea->getAccounts()->getSlug() ability of Doctrine 1.2. Where accounts is another table linked to the idea as a foreign relation. This is called several times for each idea row. A partial is not currently used to hold the code for each row element.
Is there a performance advantage to using a partial for the row element? (ignoring for now the benefit of code maintability)
What is best practice for referencing data connected via a foreign relation? I'm surprised that a call is made to the DB everytime $idea->getAccounts()->getSlug() is called.
Is there anything obvious in ubuntu that would otherwise be making sfPHPView->render() run slower than centOS?
I'll give you my thought
When using a partial for a row element, it's more easy to put it in cache, because you can affine the caching by partial.
Because you don't explicit define the relation when making the query, Doctrine won't hydrate all elements with the relation. For this point, you can manually define relations you want to hydrate. Then, your call $idea->getAccounts()->getSlug() won't perform a new query every time.
$q = $this->createQuery();
$q->leftJoin('Idea.Account');
No idea for the point 3.
PS: for the point 2, it's very common to have lots of queries in admin gen when you want to display an information from a relation (in the list view). The solution is to define the method to retrieve data:
In your generator.yml:
list:
table_method: retrieveForBackendList
In the IdeaTable:
public function retrieveForBackendList(Doctrine_Query $q)
{
$rootAlias = $q->getRootAlias();
$q->leftJoin($rootAlias . '.Account');
return $q;
}
Though I would add what else I did to improve the speed of page load in addition to jOk's recommendations.
In addition to the explicit joins I did the following:
Switched to returning a DQL Query object which was then passed to Doctrine's paginator
Changed from using include_partial() to PHP's include() which reduced the object creation time of include_partial()
Hydrate the data from the DB as an array instead of an object
Removed some foreach loops by doing more leftJoins in the DB
Used result & query caching to reduce the number of DB calls
Used view caching to reduce PHP template generation time
Interestingly, by doing 1 to 4 it made 5 and 6 more effective and easier to implement. I think there is something to be said for improving your code before jumping in with caching.
Recently I integrated Doctrine 2 ORM into CodeIgniter 2. I configured Doctrine 2 as a library and autoloaded it in CodeIgniter. Within a page I instantiate doctrine entity manager in the following way:
private static $em = null;
public function __construct() {
parent::__construct();
$this->em = $this->doctrine->em;
}
And then I start to use the Entity Manager when needed. The issue I have is that in each page request Entity Manager takes some time to initialize (appr. 1 second). This causes the user to wait until the page is loaded. Below you can see some performance results I measured:
BENCHMARKS
Loading Time: Base Classes 0.0166
Doctrine 0.0486
GetArticle 1.0441
Functions 0.0068
Controller Execution Time 1.1770
Total Execution Time 1.1938
The GetArticle function basicly makes an EntityManager->find() call:
$currentart = $this->em->find('Entities\Article', $artid);
I have to wait that 1 second even if I use the EntityManager->createQuery() method.
In every page, I have a time loss of approximately 1 second because of EntityManager's first request.
Is this common?
Does this 1 second come from the fact that EntityManager needs to establish a connection to the DB? The functions/requests after the first request are quite fast though.
The most time consuming thing that Doctrine does is load metadata for your entities, whether it's annotations, XML, or YAML. Doctrine lazy loads the metadata when possible, so you will not see the performance hit until you start using entities. Since the metadata doesn't change unless you make changes in your code, Doctrine allows you to cache the metadata across requests. DQL queries also need to be parsed into SQL, so Doctrine provides another caching configuration for this.
In a production environment you should set these caches up (it sounds like you have already, but for others reading this):
$cache = new \Doctrine\Common\Cache\ApcCache(); // or MemcacheCache
$configuration->setMetadataCachImpl($cache); // caches metadata for entities
$configuration->setQueryCachImpl($cache); // caches SQL from DQL queries
In order to prevent the first page load from taking the full metadata load, you can set up a cache warmer that loads all of the class metadata and save it to the cache.
$em->getMetadataFactory()->getAllMetadata();
Another potential bottleneck is the generation of proxy classes. If this is not configured correctly in a production environment, Doctrine will generate the classes and save them to the file system on every page load. These proxy classes do not change unless the entity's code changes, so it is again unnecessary for this to happen. To speed things up, you should generate the proxies using the command line tool (orm:generate-proxies) and disable auto-generation:
$configuration->setAutoGenerateProxyClasses(false);
Hopefully this helps you out. Some more information can be found at http://www.doctrine-project.org/docs/orm/2.0/en/reference/improving-performance.html#bytecode-cache