-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix performance issue when using notify tracking policy and calling flush($entity)
multiple times
#5579
Conversation
458f64d
to
6d50a66
Compare
@xhuberty the change looks good, but it really needs to be isolated in private API (split into private methods). |
if ($entity === null) { | ||
$this->entityChangeSets = $this->scheduledForSynchronization = array(); | ||
} elseif (is_object($entity)) { | ||
$oid = spl_object_hash($entity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will need separate tests to verify that the other changesets are still there
6d50a66
to
f0d15df
Compare
I think I made the modification you ask for except the one concerning the unit test. |
$this->orphanRemovals = array(); | ||
|
||
if ($entity === null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please reverse this (yoda)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry but I don't understand what you want. I used the exact same code as the one of the beginning of the commit method.
@xhuberty we'd need tests before merging, heh |
@Ocramius can you please tell me exactly what unit test you need/want? I tought the unit test will already covered my modifications execpt for the 2 mtethods I have created. |
I made the change with the Yoda condition. I will regroup all the commit in one when everything will be ok. |
@xhuberty a test should ideally have a UoW with 3 entries ( |
@@ -3111,7 +3133,19 @@ public function registerManaged($entity, array $id, array $data) | |||
*/ | |||
public function clearEntityChangeSet($oid) | |||
{ | |||
$this->entityChangeSets[$oid] = array(); | |||
if (isset($this->entityChangeSets[$oid])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for an isset()
check
1811e86
to
a91b5bb
Compare
I made the unit test, and I have regroup all the commit in one. |
$this->_unitOfWork->persist($entity2); | ||
|
||
$this->_unitOfWork->commit($entity1); | ||
$this->assertEquals(1, count($this->_unitOfWork->getEntityChangeSet($entity2))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use assertCount()
instead.
a91b5bb
to
f09689c
Compare
Use of assertCount and fix indentation issue. Everything regoup in the same commit. |
1073571
to
1fda01d
Compare
Hi guys, Just wanting to know if I need to change something else for this PR to be merged? And if it's going to be merged when do you thing this will be released? We really need this modification for one of our projects. We are using a fork for the moment but this is not a viable option for the future. Best regards. |
@xhuberty I won't get at merging/reviewing stuff for a while for now. This will likely be part of 2.6 though (adding milestone) |
$this->assertCount(1, $persister->getInserts()); | ||
|
||
// Create and Set first entity | ||
$entity1 = new NotifyChangedEntity; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These assertions should be moved to their own test case, with an @group 5579
annotation to identify the issue it's related to
1fda01d
to
ed3a7d3
Compare
@Ocramius thanks a lot for your answer. |
FYI: I noticed similar behaviour in |
* @param $class | ||
* @param string $oid | ||
*/ | ||
private function clearScheduledForSynchronization($class, $oid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type hint needed
} | ||
|
||
/** | ||
* @param $class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type hint needed, return type needed
} | ||
|
||
/** | ||
* @param null|object|array $entity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh dang, I really hate this sort of API signature :-(
/** | ||
* @param null|object|array $entity | ||
*/ | ||
private function postCommitClear($entity = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameter is not optional
$this->orphanRemovals = array(); | ||
|
||
if (null === $entity) { | ||
$this->entityChangeSets = $this->scheduledForSynchronization = array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use short array notation
$oid = spl_object_hash($object); | ||
$class = $this->em->getClassMetadata(get_class($object)); | ||
$this->clearEntityChangeSet($oid); | ||
$this->clearScheduledForSynchronization($class, $oid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't this method call internally calling $this->clearEntityChangeSet()
?
$this->_unitOfWork->persist($entity2); | ||
|
||
$this->_unitOfWork->commit($entity1); | ||
$this->assertCount(1, $this->_unitOfWork->getEntityChangeSet($entity2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is a count
used here, instead of simply comparing the changeset? After all, we're checking for a single entry, so a count()
operation doesn't seem to make sense to me
|
||
$this->_unitOfWork->commit([$entity1,$entity2]); | ||
$this->assertCount(1, $this->_unitOfWork->getEntityChangeSet($entity3)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whitespace to be removed here
$this->_unitOfWork->persist($entity3); | ||
|
||
$this->_unitOfWork->commit([$entity1,$entity2]); | ||
$this->assertCount(1, $this->_unitOfWork->getEntityChangeSet($entity3)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably check that there's no changeset for $entity1
and $entity2
here.
$entity3->setData('thedata'); | ||
$this->_unitOfWork->persist($entity3); | ||
|
||
$this->_unitOfWork->commit([$entity1,$entity2]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why committing $entity1
if it was already committed? (also, space after ,
)
flush($entity)
multiple times
Manually rebased, cleaned up some details and split the tests and packaged for |
…s for the tracking policy changeset clearing
Hi,
First of all I want to apologize for the poor quality of my English.
We had some performance issues in one of our project and we decide to use the Notify tracking policy.
This tracking policy is really usefull for batch and import. For your information we improved the performance of more than 80%.
During our test we discover that flush operations were cleaning the $entityChangeset of the UnitOfWork.
This is a real issue for us because we are using flush with null and entity as parameter.
Example:
With the notify tracking policy this code above will only save the change of the object1. All the other changes are lost.