[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