[TYPO3-mvc] Strange performance problem - a lot of databasequeries
Lienhart Woitok
Lienhart.Woitok at netlogix.de
Thu May 13 13:49:54 CEST 2010
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Hi Thomas,
> Is there a chance you can postyour enhanced patch of Xaver Koch
> to the mailing list or another place like the forge etc.? Then we
> all can have a look at it and figure out things better.
I actually did attach the patch to my previous mail (I just checked that again) but somehow it didn't get through to the mailing list. Thus I paste it here hoping that it will work this time.
Please copy and paste the following in a file and apply it with patch or similar.
Index: Classes/DomainObject/AbstractEntity.php
===================================================================
- --- Classes/DomainObject/AbstractEntity.php (revision 2271)
+++ Classes/DomainObject/AbstractEntity.php (working copy)
@@ -77,6 +77,7 @@
// which is currently needed in Fluid.
if ($propertyValue instanceof Tx_Extbase_DomainObject_AbstractDomainObject) {
$this->_cleanProperties[$propertyName]->_setClone(FALSE);
+ $this->_cleanProperties[$propertyName]->_setProperty('uid', $propertyValue->getUid());
}
} else {
$this->_cleanProperties[$propertyName] = $propertyValue;
@@ -119,30 +120,40 @@
if ($this->uid !== NULL && $this->uid != $this->_cleanProperties['uid']) throw new Tx_Extbase_Persistence_Exception_TooDirty('The uid "' . $this->uid . '" has been modified, that is simply too much.', 1222871239);
$result = FALSE;
if ($propertyName !== NULL) {
- - if (is_object($this->$propertyName)) {
- - // In case it is an object, we do a simple comparison (!=) as we want cloned objects to return the same values.
- - $result = $this->_cleanProperties[$propertyName] != $this->$propertyName;
- - } else {
- - $result = $this->_cleanProperties[$propertyName] !== $this->$propertyName;
- - }
+ $result = $this->_isDirtyProperty($propertyName);
} else {
foreach ($this->_cleanProperties as $propertyName => $propertyValue) {
- - if (is_object($this->$propertyName)) {
- - // In case it is an object, we do a simple comparison (!=) as we want cloned objects to return the same values.
- - if ($this->$propertyName != $propertyValue) {
- - $result = TRUE;
- - break;
- - }
- - } else {
- - if ($this->$propertyName !== $propertyValue) {
- - $result = TRUE;
- - break;
- - }
+ $result = $this->_isDirtyProperty($propertyName);
+ if ($result) {
+ break;
}
}
}
return $result;
}
- -
+
+ /**
+ * Returns TRUE if the given property was modified after reconstitution
+ *
+ * @param string $propertyName The name of a property to be checked if its value is dirty
+ * @return boolean
+ */
+ private function _isDirtyProperty($propertyName) {
+ $result = FALSE;
+ if ($propertyName !== NULL) {
+ // In case it is an object and it provides a method _isDirty, we call it instead of a simple comparison of objects.
+ // We do this, because if the object itself contains a lazy loaded property, the comparison of the objects might fail even if the object didn't change
+ if (is_object($this->$propertyName) && method_exists($this->$propertyName, '_isDirty')) {
+ $result = $this->$propertyName->_isDirty() || (($this->$propertyName instanceof Tx_Extbase_DomainObject_AbstractEntity && $this->_cleanProperties[$propertyName]->getUid() !== $this->$propertyName->getUid()) || ($this->$propertyName instanceof Tx_Extbase_DomainObject_AbstractValueObject && $this->_cleanProperties[$propertyName] != $this->$propertyName));
+ } else if (is_object($this->$propertyName)) {
+ // For all other objects we do a simple comparison (!=) as we want cloned objects to return the same values.
+ $result = $this->_cleanProperties[$propertyName] != $this->$propertyName;
+ } else {
+ $result = $this->_cleanProperties[$propertyName] !== $this->$propertyName;
+ }
+ }
+ return $result;
+ }
+
}
?>
\ No newline at end of file
Index: Classes/Persistence/Backend.php
===================================================================
- --- Classes/Persistence/Backend.php (revision 2271)
+++ Classes/Persistence/Backend.php (working copy)
@@ -441,7 +441,7 @@
public function propertyValueIsLazyLoaded($propertyValue) {
if ($propertyValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy) return TRUE;
if (is_object($propertyValue) && get_class($propertyValue) === 'Tx_Extbase_Persistence_LazyObjectStorage') {
- - if ($propertyValue->isInitialized() === FALSE) {
+ if ($propertyValue->isInitialized() === FALSE || !$propertyValue->_isDirty()) {
return TRUE;
}
}
@@ -466,9 +466,7 @@
$properties = $object->_getProperties();
foreach ($properties as $propertyName => $propertyValue) {
if (!$dataMap->isPersistableProperty($propertyName)) continue;
- - if (($propertyValue instanceof Tx_Extbase_Persistence_LazyLoadingProxy) || ((get_class($propertyValue) === 'Tx_Extbase_Persistence_LazyObjectStorage') && ($propertyValue->isInitialized() === FALSE))) {
- - continue;
- - }
+ if (!$dataMap->isPersistableProperty($propertyName) || $this->propertyValueIsLazyLoaded($propertyValue)) continue;
$columnMap = $dataMap->getColumnMap($propertyName);
$propertyMetaData = $classSchema->getProperty($propertyName);
Index: Classes/Persistence/LazyObjectStorage.php
===================================================================
- --- Classes/Persistence/LazyObjectStorage.php (revision 2271)
+++ Classes/Persistence/LazyObjectStorage.php (working copy)
@@ -91,6 +91,7 @@
$this->storage = $storage;
$this->parentObject->_memorizeCleanState($this->propertyName);
$this->isInitialized = TRUE;
+ $this->_memorizeCleanState();
}
}
Index: Classes/Persistence/ObjectStorage.php
===================================================================
- --- Classes/Persistence/ObjectStorage.php (revision 2271)
+++ Classes/Persistence/ObjectStorage.php (working copy)
@@ -46,6 +46,12 @@
protected $isInitialized = TRUE;
/**
+ * Flag if the object storage has been modified (items got added, replaced, removed)
+ * @var bool
+ */
+ protected $isModified = FALSE;
+
+ /**
* This is a template function to be overwritten by a concrete implementation. It enables you to implement
* a lazy load implementation.
*
@@ -66,11 +72,12 @@
/**
* Resets the array pointer of the storage
*
- - * @return void
+ * @return self which allows for chaining
*/
public function rewind() {
$this->initializeStorage();
reset($this->storage);
+ return $this;
}
/**
@@ -110,7 +117,7 @@
*/
public function next() {
$this->initializeStorage();
- - next($this->storage);
+ return next($this->storage);
}
/**
@@ -138,6 +145,7 @@
$this->initializeStorage();
if (!$this->contains($offset)) {
$this->storage[spl_object_hash($offset)] = $value;
+ $this->isModified = true;
}
}
@@ -162,7 +170,10 @@
public function offsetUnset($offset) {
$this->isObject($offset);
$this->initializeStorage();
- - unset($this->storage[spl_object_hash($offset)]);
+ if ($this->offsetExists($offset)) {
+ unset($this->storage[spl_object_hash($offset)]);
+ $this->isModified = TRUE;
+ }
}
/**
@@ -198,12 +209,13 @@
public function attach($object, $value = NULL) {
$this->isObject($object);
$this->initializeStorage();
- - if (!$this->contains($object)) {
- - if ($value === NULL) {
- - $value = $object;
- - }
+ if ($value === NULL) {
+ $value = $object;
+ }
+ if (!$this->contains($value)) {
// TODO Revise this with Karsten
$this->storage[spl_object_hash($object)] = $value;
+ $this->isModified = true;
}
}
@@ -216,7 +228,10 @@
public function detach($object) {
$this->isObject($object);
$this->initializeStorage();
- - unset($this->storage[spl_object_hash($object)]);
+ if ($this->contains($object)) {
+ unset($this->storage[spl_object_hash($object)]);
+ $this->isModified = true;
+ }
}
/**
@@ -272,6 +287,26 @@
return $this->storage;
}
+ /**
+ * Register the clean state of the object storage, e.g. after it has been populated
+ *
+ * @return void
+ */
+ public function _memorizeCleanState() {
+ $this->isModified = FALSE;
+ }
+
+ /**
+ * Return boolean true or false if the content of the ObjectStorage got changed or is itself "dirty"
+ *
+ * @return bool TRUE/FALSE
+ */
+ public function _isDirty() {
+ if ($this->isModified) {
+ return TRUE;
+ }
+ return FALSE;
+ }
}
?>
\ No newline at end of file
Index: Classes/Persistence/Mapper/DataMapper.php
===================================================================
- --- Classes/Persistence/Mapper/DataMapper.php (revision 2271)
+++ Classes/Persistence/Mapper/DataMapper.php (working copy)
@@ -443,14 +493,14 @@
$propertyValue = new ArrayObject($objects);
} elseif ($propertyMetaData['type'] === 'Tx_Extbase_Persistence_ObjectStorage') {
$propertyValue = new Tx_Extbase_Persistence_ObjectStorage();
- - foreach ($objects as $object) {
- - $propertyValue->attach($object);
- - }
+ $propertyValue->addAll($objects);
+ // we need to memorize the clean state of the object storage here, in order to be able to determin changes after it got initially populated
+ $propertyValue->_memorizeCleanState();
} else {
$propertyValue = $objects;
}
} elseif (strpos($propertyMetaData['type'], '_') !== FALSE) {
- - $propertyValue = current($result);
+ $propertyValue = $result === NULL ? NULL : current($result);
}
}
return $propertyValue;
END OF PATCH
Sorry for the inconvienece.
Regards,
Lienhart Woitok
Web-Entwickler
Telefon: +49 (911) 539909 - 0
E-Mail: Lienhart.Woitok at netlogix.de
- --
netlogix GmbH & Co. KG
Systemhaus | Trainingscenter | Medienagentur
Andernacher Straße 53 | 90411 Nürnberg
Telefon: +49 (911) 539909 - 0 | Fax: +49 (911) 539909 - 99
E-Mail: mailto:info at netlogix.de | Internet: http://www.netlogix.de/
netlogix GmbH & Co. KG ist eingetragen am Amtsgericht Nürnberg (HRA 13338)
Persönlich haftende Gesellschafterin: netlogix Verwaltungs GmbH (HRB 20634)
Umsatzsteuer-Identifikationsnummer: DE 233472254
Geschäftsführer: Stefan Buchta, Matthias Schmidt
-----BEGIN PGP SIGNATURE-----
Version: PGP Universal 3.0.0 (Build 2881)
Charset: Windows-1252
wpUDBQFL6+dlWevMF2ftbKMBCJqkA/4sHWfLvJYkVeBTjMIwnqFZLL3O6NxSp4rr
fYozo7/2m2UPb7HNzWxw+VC9R9ha7c6telqFxP853NeT5TmeYkq2ui09UCoHODg4
w0taPx5dXTLIJ7ZrNG3gqtbyaaXaSqMIM5n9NK0R/cnWsRTnwk12yFP966J26+xi
d0YaILKRqw==
=broS
-----END PGP SIGNATURE-----
More information about the TYPO3-project-typo3v4mvc
mailing list