From c8a41598c9fd065727a35ef636c3c3b4c627dbad Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:17:30 +0200 Subject: [PATCH 01/33] Not a performance test --- .../Doctrine/Tests/ORM/Performance/DDC2602Test.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Performance/DDC2602Test.php b/tests/Doctrine/Tests/ORM/Performance/DDC2602Test.php index 618b5f9c6..de8bedfc7 100644 --- a/tests/Doctrine/Tests/ORM/Performance/DDC2602Test.php +++ b/tests/Doctrine/Tests/ORM/Performance/DDC2602Test.php @@ -8,7 +8,6 @@ use Doctrine\ORM\Events; use Doctrine\Tests\OrmPerformanceTestCase; /** - * @group performance * @group DDC-2602 */ class DDC2602Test extends OrmPerformanceTestCase @@ -51,14 +50,10 @@ class DDC2602Test extends OrmPerformanceTestCase // Set maximum seconds this can run $this->setMaxRunningTime(1); - $s = microtime(true); - - $query = $this->_em->createQuery('SELECT u, b FROM Doctrine\Tests\ORM\Performance\DDC2602User u JOIN u.biography b'); - $query->getResult(); - - $e = microtime(true); - - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; + $this + ->_em + ->createQuery('SELECT u, b FROM Doctrine\Tests\ORM\Performance\DDC2602User u JOIN u.biography b') + ->getResult(); } private function loadFixture() From 25669c51b604fb8bf7ee3d8cde48496699f3873b Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:17:41 +0200 Subject: [PATCH 02/33] PHPBench base config --- .gitignore | 1 + phpbench.json | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 phpbench.json diff --git a/.gitignore b/.gitignore index 490413d15..d2f5f6901 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ lib/Doctrine/DBAL .idea vendor/ composer.lock +/tests/Doctrine/Performance/history.db diff --git a/phpbench.json b/phpbench.json new file mode 100644 index 000000000..74fdef412 --- /dev/null +++ b/phpbench.json @@ -0,0 +1,15 @@ +{ + "bootstrap": "vendor/autoload.php", + "path": "tests/Doctrine/Performance", + + "extensions": [ + "PhpBench\\Extensions\\Dbal\\DbalExtension", + "PhpBench\\Extensions\\XDebug\\XDebugExtension" + ], + + "storage": "dbal", + "storage.dbal.connection": { + "driver": "pdo_sqlite", + "path": "tests/Doctrine/Performance/history.db" + } +} From 37cb2c0722161d27eff2def8da3efd81c4250307 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:17:56 +0200 Subject: [PATCH 03/33] Benchmark autoloading definitions --- composer.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d320b0b4d..d632c8991 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,10 @@ "psr-4": { "Doctrine\\ORM\\": "lib/Doctrine/ORM" } }, "autoload-dev": { - "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine/Tests" } + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests", + "Doctrine\\Performance\\": "tests/Doctrine/Performance" + } }, "bin": ["bin/doctrine"], "extra": { From 94adf9755023d611eed424995660683738272ced Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:49:39 +0200 Subject: [PATCH 04/33] Factory used to create a new entity manager --- .../Performance/EntityManagerFactory.php | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/Doctrine/Performance/EntityManagerFactory.php diff --git a/tests/Doctrine/Performance/EntityManagerFactory.php b/tests/Doctrine/Performance/EntityManagerFactory.php new file mode 100644 index 000000000..fab5eba76 --- /dev/null +++ b/tests/Doctrine/Performance/EntityManagerFactory.php @@ -0,0 +1,39 @@ +setProxyDir(__DIR__ . '/../Tests/Proxies'); + $config->setProxyNamespace('Doctrine\Tests\Proxies'); + $config->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_EVAL); + $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver([ + realpath(__DIR__ . '/Models/Cache'), + realpath(__DIR__ . '/Models/GeoNames') + ], true)); + + $entityManager = EntityManager::create( + [ + 'driverClass' => Driver::class, + 'memory' => true, + ], + $config + ); + + (new SchemaTool($entityManager)) + ->createSchema(array_map([$entityManager, 'getClassMetadata'], $schemaClassNames)); + + return $entityManager; + } +} From f95c81b21018394004a2368c13a0b94715012093 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:49:56 +0200 Subject: [PATCH 05/33] Simple array hydration benchmark --- ...leQueryScalarHydrationPerformanceBench.php | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php new file mode 100644 index 000000000..298aaf86b --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php @@ -0,0 +1,83 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ], + [ + 'u__id' => '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ], + [ + 'u__id' => '2', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ] + ]; + + for ($i = 4; $i < 10000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ScalarHydrator($entityManager); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + } + + public function benchSimpleQueryScalarHydrationPerformance() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm); + } +} + From 88ea1d33fa92e26bcc44ed1a42b172af1b780c10 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:50:11 +0200 Subject: [PATCH 06/33] Full hydration + query benchmark --- .../Hydration/SimpleHydrationBench.php | 58 +++++++++++++++++++ .../ORM/Functional/Ticket/DDC1050Test.php | 39 ------------- 2 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php delete mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1050Test.php diff --git a/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php b/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php new file mode 100644 index 000000000..c1bc1d61d --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php @@ -0,0 +1,58 @@ +entityManager = EntityManagerFactory::getEntityManager([ + \Doctrine\Tests\Models\CMS\CmsUser::class, + \Doctrine\Tests\Models\CMS\CmsPhonenumber::class, + \Doctrine\Tests\Models\CMS\CmsAddress::class, + \Doctrine\Tests\Models\CMS\CmsEmail::class, + \Doctrine\Tests\Models\CMS\CmsGroup::class, + \Doctrine\Tests\Models\CMS\CmsTag::class, + \Doctrine\Tests\Models\CMS\CmsArticle::class, + \Doctrine\Tests\Models\CMS\CmsComment::class, + ]); + + for ($i = 2; $i < 10000; ++$i) { + $user = new CmsUser(); + + $user->status = 'developer'; + $user->username = 'jwage' . $i; + $user->name = 'Jonathan'; + + $this->entityManager->persist($user); + } + + $this->entityManager->flush(); + $this->entityManager->clear(); + + $this->repository = $this->entityManager->getRepository(CmsUser::class); + } + + public function benchSimpleFindOperationHydration() + { + $this->repository->findAll(); + } +} diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1050Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1050Test.php deleted file mode 100644 index 12c3898d8..000000000 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1050Test.php +++ /dev/null @@ -1,39 +0,0 @@ -markTestSkipped('performance skipped'); - - $this->useModelSet('cms'); - - parent::setUp(); - } - - public function testPerformance() - { - for ($i = 2; $i < 10000; ++$i) { - $user = new CmsUser(); - $user->status = 'developer'; - $user->username = 'jwage'.$i; - $user->name = 'Jonathan'; - $this->_em->persist($user); - } - $this->_em->flush(); - $this->_em->clear(); - - $s = microtime(true); - $users = $this->_em->getRepository(CmsUser::class)->findAll(); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } -} From d8ddc47f83840bf16870d5873bf91e675aeaad4b Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:52:18 +0200 Subject: [PATCH 07/33] Array hydration benchmark --- ...pleQueryArrayHydrationPerformanceBench.php | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php new file mode 100644 index 000000000..9ff8a1f9b --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php @@ -0,0 +1,83 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ], + [ + 'u__id' => '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ], + [ + 'u__id' => '2', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ] + ]; + + for ($i = 4; $i < 10000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ArrayHydrator($entityManager); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + } + + public function benchSimpleQueryScalarHydrationPerformance() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm); + } +} + From 8774b02c8884f4af30403fd1b5d4f62d7a9d6324 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:57:40 +0200 Subject: [PATCH 08/33] Testing mixed array hydration (with scalars and fetch-joined results) --- ...etchJoinArrayHydrationPerformanceBench.php | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php new file mode 100644 index 000000000..31757f940 --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php @@ -0,0 +1,94 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'ROMANB', + 'p__phonenumber' => '42', + ], + [ + 'u__id' => '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'ROMANB', + 'p__phonenumber' => '43', + ], + [ + 'u__id' => '2', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'JWAGE', + 'p__phonenumber' => '91' + ] + ]; + + for ($i = 4; $i < 10000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + 'sclr0' => 'JWAGE' . $i, + 'p__phonenumber' => '91' + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ArrayHydrator($entityManager); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + $this->rsm->addScalarResult('sclr0', 'nameUpper'); + $this->rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); + } + + public function benchSimpleQueryScalarHydrationPerformance() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm); + } +} + From 0fdcc7188705333c282da948910c09bdd9c0d21c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 20:57:50 +0200 Subject: [PATCH 09/33] CS (alignment) --- ...pleQueryArrayHydrationPerformanceBench.php | 24 +++++++++---------- ...leQueryScalarHydrationPerformanceBench.php | 24 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php index 9ff8a1f9b..4e19ad8b3 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php @@ -36,31 +36,31 @@ final class SimpleQueryArrayHydrationPerformanceBench $resultSet = [ [ - 'u__id' => '1', - 'u__status' => 'developer', + 'u__id' => '1', + 'u__status' => 'developer', 'u__username' => 'romanb', - 'u__name' => 'Roman', + 'u__name' => 'Roman', ], [ - 'u__id' => '1', - 'u__status' => 'developer', + 'u__id' => '1', + 'u__status' => 'developer', 'u__username' => 'romanb', - 'u__name' => 'Roman', + 'u__name' => 'Roman', ], [ - 'u__id' => '2', - 'u__status' => 'developer', + 'u__id' => '2', + 'u__status' => 'developer', 'u__username' => 'romanb', - 'u__name' => 'Roman', + 'u__name' => 'Roman', ] ]; for ($i = 4; $i < 10000; ++$i) { $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', + 'u__id' => $i, + 'u__status' => 'developer', 'u__username' => 'jwage', - 'u__name' => 'Jonathan', + 'u__name' => 'Jonathan', ]; } diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php index 298aaf86b..47242bd8e 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php @@ -36,31 +36,31 @@ final class SimpleQueryScalarHydrationPerformanceBench $resultSet = [ [ - 'u__id' => '1', - 'u__status' => 'developer', + 'u__id' => '1', + 'u__status' => 'developer', 'u__username' => 'romanb', - 'u__name' => 'Roman', + 'u__name' => 'Roman', ], [ - 'u__id' => '1', - 'u__status' => 'developer', + 'u__id' => '1', + 'u__status' => 'developer', 'u__username' => 'romanb', - 'u__name' => 'Roman', + 'u__name' => 'Roman', ], [ - 'u__id' => '2', - 'u__status' => 'developer', + 'u__id' => '2', + 'u__status' => 'developer', 'u__username' => 'romanb', - 'u__name' => 'Roman', + 'u__name' => 'Roman', ] ]; for ($i = 4; $i < 10000; ++$i) { $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', + 'u__id' => $i, + 'u__status' => 'developer', 'u__username' => 'jwage', - 'u__name' => 'Jonathan', + 'u__name' => 'Jonathan', ]; } From f23359c1f38efaf2be8a8267f36eb60898b34bb1 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:04:35 +0200 Subject: [PATCH 10/33] Renaming bench methods, for clarity --- .../MixedQueryFetchJoinArrayHydrationPerformanceBench.php | 2 +- tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php | 2 +- .../Hydration/SimpleQueryArrayHydrationPerformanceBench.php | 2 +- .../Hydration/SimpleQueryScalarHydrationPerformanceBench.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php index 31757f940..478f0b44d 100644 --- a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php @@ -86,7 +86,7 @@ final class MixedQueryFetchJoinArrayHydrationPerformanceBench $this->rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); } - public function benchSimpleQueryScalarHydrationPerformance() + public function benchHydration() { $this->hydrator->hydrateAll($this->stmt, $this->rsm); } diff --git a/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php b/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php index c1bc1d61d..b3ecbab2e 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php @@ -51,7 +51,7 @@ final class SimpleHydrationBench $this->repository = $this->entityManager->getRepository(CmsUser::class); } - public function benchSimpleFindOperationHydration() + public function benchHydration() { $this->repository->findAll(); } diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php index 4e19ad8b3..10081245d 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php @@ -75,7 +75,7 @@ final class SimpleQueryArrayHydrationPerformanceBench $this->rsm->addFieldResult('u', 'u__name', 'name'); } - public function benchSimpleQueryScalarHydrationPerformance() + public function benchHydration() { $this->hydrator->hydrateAll($this->stmt, $this->rsm); } diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php index 47242bd8e..030b3667b 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php @@ -75,7 +75,7 @@ final class SimpleQueryScalarHydrationPerformanceBench $this->rsm->addFieldResult('u', 'u__name', 'name'); } - public function benchSimpleQueryScalarHydrationPerformance() + public function benchHydration() { $this->hydrator->hydrateAll($this->stmt, $this->rsm); } From 97735cdb68db18a76779886d0d061ec0a1e03763 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:12:43 +0200 Subject: [PATCH 11/33] Partial hydration bench --- ...PartialObjectHydrationPerformanceBench.php | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php new file mode 100644 index 000000000..cbbc24e1b --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php @@ -0,0 +1,83 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ], + [ + 'u__id' => '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ], + [ + 'u__id' => '2', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + ] + ]; + + for ($i = 4; $i < 10000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ObjectHydrator($entityManager); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + } + + public function benchHydration() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); + } +} + From 1e16cb83f847a228b6209f326f7cc610831a427c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:21:26 +0200 Subject: [PATCH 12/33] Full object hydration benchmark --- ...eryFullObjectHydrationPerformanceBench.php | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php new file mode 100644 index 000000000..fc61b9240 --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php @@ -0,0 +1,76 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'a__id' => '1' + ] + ]; + + for ($i = 2; $i < 10000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + 'a__id' => $i + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ObjectHydrator($entityManager); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + $this->rsm->addJoinedEntityResult(CmsAddress::class, 'a', 'u', 'address'); + $this->rsm->addFieldResult('a', 'a__id', 'id'); + } + + public function benchHydration() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm); + } +} + From 131aac531ad8e4dc8eaf91b853057544bb7dfed7 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:25:06 +0200 Subject: [PATCH 13/33] Removing unused `$entityManager` variable --- .../MixedQueryFetchJoinArrayHydrationPerformanceBench.php | 4 +--- .../Hydration/SimpleQueryArrayHydrationPerformanceBench.php | 4 +--- .../SimpleQueryFullObjectHydrationPerformanceBench.php | 4 +--- .../SimpleQueryPartialObjectHydrationPerformanceBench.php | 4 +--- .../Hydration/SimpleQueryScalarHydrationPerformanceBench.php | 4 +--- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php index 478f0b44d..bbda1f23d 100644 --- a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinArrayHydrationPerformanceBench.php @@ -32,8 +32,6 @@ final class MixedQueryFetchJoinArrayHydrationPerformanceBench public function init() { - $entityManager = EntityManagerFactory::getEntityManager([]); - $resultSet = [ [ 'u__id' => '1', @@ -73,7 +71,7 @@ final class MixedQueryFetchJoinArrayHydrationPerformanceBench } $this->stmt = new HydratorMockStatement($resultSet); - $this->hydrator = new ArrayHydrator($entityManager); + $this->hydrator = new ArrayHydrator(EntityManagerFactory::getEntityManager([])); $this->rsm = new ResultSetMapping; $this->rsm->addEntityResult(CmsUser::class, 'u'); diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php index 10081245d..aa404554d 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryArrayHydrationPerformanceBench.php @@ -32,8 +32,6 @@ final class SimpleQueryArrayHydrationPerformanceBench public function init() { - $entityManager = EntityManagerFactory::getEntityManager([]); - $resultSet = [ [ 'u__id' => '1', @@ -65,7 +63,7 @@ final class SimpleQueryArrayHydrationPerformanceBench } $this->stmt = new HydratorMockStatement($resultSet); - $this->hydrator = new ArrayHydrator($entityManager); + $this->hydrator = new ArrayHydrator(EntityManagerFactory::getEntityManager([])); $this->rsm = new ResultSetMapping; $this->rsm->addEntityResult(CmsUser::class, 'u'); diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php index fc61b9240..173001ff8 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryFullObjectHydrationPerformanceBench.php @@ -33,8 +33,6 @@ final class SimpleQueryFullObjectHydrationPerformanceBench public function init() { - $entityManager = EntityManagerFactory::getEntityManager([]); - $resultSet = [ [ 'u__id' => '1', @@ -56,7 +54,7 @@ final class SimpleQueryFullObjectHydrationPerformanceBench } $this->stmt = new HydratorMockStatement($resultSet); - $this->hydrator = new ObjectHydrator($entityManager); + $this->hydrator = new ObjectHydrator(EntityManagerFactory::getEntityManager([])); $this->rsm = new ResultSetMapping; $this->rsm->addEntityResult(CmsUser::class, 'u'); diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php index cbbc24e1b..55d78973f 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryPartialObjectHydrationPerformanceBench.php @@ -32,8 +32,6 @@ final class SimpleQueryPartialObjectHydrationPerformanceBench public function init() { - $entityManager = EntityManagerFactory::getEntityManager([]); - $resultSet = [ [ 'u__id' => '1', @@ -65,7 +63,7 @@ final class SimpleQueryPartialObjectHydrationPerformanceBench } $this->stmt = new HydratorMockStatement($resultSet); - $this->hydrator = new ObjectHydrator($entityManager); + $this->hydrator = new ObjectHydrator(EntityManagerFactory::getEntityManager([])); $this->rsm = new ResultSetMapping; $this->rsm->addEntityResult(CmsUser::class, 'u'); diff --git a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php index 030b3667b..4af2c0791 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleQueryScalarHydrationPerformanceBench.php @@ -32,8 +32,6 @@ final class SimpleQueryScalarHydrationPerformanceBench public function init() { - $entityManager = EntityManagerFactory::getEntityManager([]); - $resultSet = [ [ 'u__id' => '1', @@ -65,7 +63,7 @@ final class SimpleQueryScalarHydrationPerformanceBench } $this->stmt = new HydratorMockStatement($resultSet); - $this->hydrator = new ScalarHydrator($entityManager); + $this->hydrator = new ScalarHydrator(EntityManagerFactory::getEntityManager([])); $this->rsm = new ResultSetMapping; $this->rsm->addEntityResult(CmsUser::class, 'u'); From 608b3ed6a4bf324464a4892c4c84075d734bb6d9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:26:55 +0200 Subject: [PATCH 14/33] Benchmarking mixed fetch-join with partial hydration --- ...PartialObjectHydrationPerformanceBench.php | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinPartialObjectHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinPartialObjectHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinPartialObjectHydrationPerformanceBench.php new file mode 100644 index 000000000..f2e33f76d --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinPartialObjectHydrationPerformanceBench.php @@ -0,0 +1,93 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'ROMANB', + 'p__phonenumber' => '42', + ], + [ + 'u__id' => '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'ROMANB', + 'p__phonenumber' => '43', + ], + [ + 'u__id' => '2', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'JWAGE', + 'p__phonenumber' => '91' + ] + ]; + + for ($i = 4; $i < 2000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + 'sclr0' => 'JWAGE' . $i, + 'p__phonenumber' => '91' + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ObjectHydrator(EntityManagerFactory::getEntityManager([])); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + $this->rsm->addScalarResult('sclr0', 'nameUpper'); + $this->rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); + } + + public function benchHydration() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); + } +} + From 93dc02819484cfef1402cd6853191965fb6b5e5a Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:29:26 +0200 Subject: [PATCH 15/33] Benchmarking full object hydration with fetch joins and mixed values --- ...oinFullObjectHydrationPerformanceBench.php | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinFullObjectHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinFullObjectHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinFullObjectHydrationPerformanceBench.php new file mode 100644 index 000000000..c70ca77cb --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/MixedQueryFetchJoinFullObjectHydrationPerformanceBench.php @@ -0,0 +1,81 @@ + '1', + 'u__status' => 'developer', + 'u__username' => 'romanb', + 'u__name' => 'Roman', + 'sclr0' => 'ROMANB', + 'p__phonenumber' => '42', + 'a__id' => '1' + ] + ]; + + for ($i = 2; $i < 2000; ++$i) { + $resultSet[] = [ + 'u__id' => $i, + 'u__status' => 'developer', + 'u__username' => 'jwage', + 'u__name' => 'Jonathan', + 'sclr0' => 'JWAGE' . $i, + 'p__phonenumber' => '91', + 'a__id' => $i + ]; + } + + $this->stmt = new HydratorMockStatement($resultSet); + $this->hydrator = new ObjectHydrator(EntityManagerFactory::getEntityManager([])); + $this->rsm = new ResultSetMapping; + + $this->rsm->addEntityResult(CmsUser::class, 'u'); + $this->rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers'); + $this->rsm->addFieldResult('u', 'u__id', 'id'); + $this->rsm->addFieldResult('u', 'u__status', 'status'); + $this->rsm->addFieldResult('u', 'u__username', 'username'); + $this->rsm->addFieldResult('u', 'u__name', 'name'); + $this->rsm->addScalarResult('sclr0', 'nameUpper'); + $this->rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); + $this->rsm->addJoinedEntityResult(CmsAddress::class, 'a', 'u', 'address'); + $this->rsm->addFieldResult('a', 'a__id', 'id'); + } + + public function benchHydration() + { + $this->hydrator->hydrateAll($this->stmt, $this->rsm); + } +} + From fd27b22ad1755b9d76021cf1dc00b62c9c6d12a6 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:29:50 +0200 Subject: [PATCH 16/33] Removing old `HydrationPerformanceTest` --- .../Performance/HydrationPerformanceTest.php | 456 ------------------ 1 file changed, 456 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Performance/HydrationPerformanceTest.php diff --git a/tests/Doctrine/Tests/ORM/Performance/HydrationPerformanceTest.php b/tests/Doctrine/Tests/ORM/Performance/HydrationPerformanceTest.php deleted file mode 100644 index 0035222ad..000000000 --- a/tests/Doctrine/Tests/ORM/Performance/HydrationPerformanceTest.php +++ /dev/null @@ -1,456 +0,0 @@ - 0.7 seconds] - * - * MAXIMUM TIME: 1 second - */ - public function testSimpleQueryScalarHydrationPerformance10000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ], - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ], - [ - 'u__id' => '2', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ] - ]; - - for ($i = 4; $i < 10000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ScalarHydrator($this->_em); - - $this->setMaxRunningTime(1); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } - - /** - * Times for comparison: - * - * [romanb: 10000 rows => 1 second] - * - * MAXIMUM TIME: 2 seconds - */ - public function testSimpleQueryArrayHydrationPerformance10000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ], - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ], - [ - 'u__id' => '2', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ] - ]; - - for ($i = 4; $i < 10000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ArrayHydrator($this->_em); - - $this->setMaxRunningTime(2); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } - - /** - * Times for comparison: - * - * [romanb: 10000 rows => 1.4 seconds] - * - * MAXIMUM TIME: 3 seconds - */ - public function testMixedQueryFetchJoinArrayHydrationPerformance10000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addJoinedEntityResult( - CmsPhonenumber::class, - 'p', - 'u', - 'phonenumbers' - ); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - $rsm->addScalarResult('sclr0', 'nameUpper'); - $rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'ROMANB', - 'p__phonenumber' => '42', - ], - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'ROMANB', - 'p__phonenumber' => '43', - ], - [ - 'u__id' => '2', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'JWAGE', - 'p__phonenumber' => '91' - ] - ]; - - for ($i = 4; $i < 10000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - 'sclr0' => 'JWAGE' . $i, - 'p__phonenumber' => '91' - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ArrayHydrator($this->_em); - - $this->setMaxRunningTime(3); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } - - /** - * [romanb: 10000 rows => 1.5 seconds] - * - * MAXIMUM TIME: 3 seconds - */ - public function testSimpleQueryPartialObjectHydrationPerformance10000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ], - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ], - [ - 'u__id' => '2', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - ] - ]; - - for ($i = 4; $i < 10000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ObjectHydrator($this->_em); - - $this->setMaxRunningTime(3); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } - - /** - * [romanb: 10000 rows => 3 seconds] - * - * MAXIMUM TIME: 4.5 seconds - */ - public function testSimpleQueryFullObjectHydrationPerformance10000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - $rsm->addJoinedEntityResult( - CmsAddress::class, - 'a', - 'u', - 'address' - ); - $rsm->addFieldResult('a', 'a__id', 'id'); - //$rsm->addFieldResult('a', 'a__country', 'country'); - //$rsm->addFieldResult('a', 'a__zip', 'zip'); - //$rsm->addFieldResult('a', 'a__city', 'city'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'a__id' => '1' - ] - ]; - - for ($i = 2; $i < 10000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - 'a__id' => $i - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ObjectHydrator($this->_em); - - $this->setMaxRunningTime(5); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } - - /** - * [romanb: 2000 rows => 0.4 seconds] - * - * MAXIMUM TIME: 1 second - */ - public function testMixedQueryFetchJoinPartialObjectHydrationPerformance2000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addJoinedEntityResult( - CmsPhonenumber::class, - 'p', - 'u', - 'phonenumbers' - ); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - $rsm->addScalarResult('sclr0', 'nameUpper'); - $rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'ROMANB', - 'p__phonenumber' => '42', - ], - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'ROMANB', - 'p__phonenumber' => '43', - ], - [ - 'u__id' => '2', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'JWAGE', - 'p__phonenumber' => '91' - ] - ]; - - for ($i = 4; $i < 2000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - 'sclr0' => 'JWAGE' . $i, - 'p__phonenumber' => '91' - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ObjectHydrator($this->_em); - - $this->setMaxRunningTime(1); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm, [Query::HINT_FORCE_PARTIAL_LOAD => true]); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } - - /** - * [romanb: 2000 rows => 0.6 seconds] - * - * MAXIMUM TIME: 1 second - */ - public function testMixedQueryFetchJoinFullObjectHydrationPerformance2000Rows() - { - $rsm = new ResultSetMapping; - $rsm->addEntityResult(CmsUser::class, 'u'); - $rsm->addJoinedEntityResult(CmsPhonenumber::class, 'p', 'u', 'phonenumbers'); - $rsm->addFieldResult('u', 'u__id', 'id'); - $rsm->addFieldResult('u', 'u__status', 'status'); - $rsm->addFieldResult('u', 'u__username', 'username'); - $rsm->addFieldResult('u', 'u__name', 'name'); - $rsm->addScalarResult('sclr0', 'nameUpper'); - $rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber'); - $rsm->addJoinedEntityResult(CmsAddress::class, 'a', 'u', 'address'); - $rsm->addFieldResult('a', 'a__id', 'id'); - - // Faked result set - $resultSet = [ - //row1 - [ - 'u__id' => '1', - 'u__status' => 'developer', - 'u__username' => 'romanb', - 'u__name' => 'Roman', - 'sclr0' => 'ROMANB', - 'p__phonenumber' => '42', - 'a__id' => '1' - ] - ]; - - for ($i = 2; $i < 2000; ++$i) { - $resultSet[] = [ - 'u__id' => $i, - 'u__status' => 'developer', - 'u__username' => 'jwage', - 'u__name' => 'Jonathan', - 'sclr0' => 'JWAGE' . $i, - 'p__phonenumber' => '91', - 'a__id' => $i - ]; - } - - $stmt = new HydratorMockStatement($resultSet); - $hydrator = new ObjectHydrator($this->_em); - - $this->setMaxRunningTime(1); - $s = microtime(true); - $result = $hydrator->hydrateAll($stmt, $rsm); - $e = microtime(true); - echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL; - } -} - From ef0edc892935e8dd2eced5443a3aca9bc7b2b5e8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:45:23 +0200 Subject: [PATCH 17/33] Benchmarking simple insert operations (batched) --- .../Hydration/SimpleInsertPerformanceTest.php | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php diff --git a/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php b/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php new file mode 100644 index 000000000..48ec971ca --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php @@ -0,0 +1,54 @@ +entityManager = EntityManagerFactory::getEntityManager([ + CMS\CmsUser::class, + CMS\CmsPhonenumber::class, + CMS\CmsAddress::class, + CMS\CmsEmail::class, + CMS\CmsGroup::class, + CMS\CmsTag::class, + CMS\CmsArticle::class, + CMS\CmsComment::class, + ]); + } + + public function benchHydration() + { + $batchSize = 20; + + for ($i = 1; $i <= 10000; ++$i) { + $user = new CMS\CmsUser; + $user->status = 'user'; + $user->username = 'user' . $i; + $user->name = 'Mr.Smith-' . $i; + + $this->entityManager->persist($user); + + if (! ($i % $batchSize)) { + $this->entityManager->flush(); + $this->entityManager->clear(); + } + } + } +} From cbb0c1bd0408e51dcb3740111086dd9d84ec00fc Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:46:02 +0200 Subject: [PATCH 18/33] Corrected class name - needs to end with `Bench` --- ...sertPerformanceTest.php => SimpleInsertPerformanceBench.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/Doctrine/Performance/Hydration/{SimpleInsertPerformanceTest.php => SimpleInsertPerformanceBench.php} (96%) diff --git a/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php b/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php similarity index 96% rename from tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php rename to tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php index 48ec971ca..5ab8906ed 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceTest.php +++ b/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php @@ -12,7 +12,7 @@ use PhpBench\Benchmark\Metadata\Annotations\BeforeMethods; /** * @BeforeMethods({"init"}) */ -final class SimpleInsertPerformanceTest +final class SimpleInsertPerformanceBench { /** * @var EntityManagerInterface From d51235f200dae6ac68bbeea8df2372310519fddf Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:46:24 +0200 Subject: [PATCH 19/33] Removing useless imports --- .../Hydration/SimpleHydrationBench.php | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php b/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php index b3ecbab2e..a3fd637d6 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleHydrationBench.php @@ -5,7 +5,7 @@ namespace Doctrine\Performance\Hydration; use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\ORM\EntityManagerInterface; use Doctrine\Performance\EntityManagerFactory; -use Doctrine\Tests\Models\CMS\CmsUser; +use Doctrine\Tests\Models\CMS; /** * @BeforeMethods({"init"}) @@ -25,18 +25,18 @@ final class SimpleHydrationBench public function init() { $this->entityManager = EntityManagerFactory::getEntityManager([ - \Doctrine\Tests\Models\CMS\CmsUser::class, - \Doctrine\Tests\Models\CMS\CmsPhonenumber::class, - \Doctrine\Tests\Models\CMS\CmsAddress::class, - \Doctrine\Tests\Models\CMS\CmsEmail::class, - \Doctrine\Tests\Models\CMS\CmsGroup::class, - \Doctrine\Tests\Models\CMS\CmsTag::class, - \Doctrine\Tests\Models\CMS\CmsArticle::class, - \Doctrine\Tests\Models\CMS\CmsComment::class, + CMS\CmsUser::class, + CMS\CmsPhonenumber::class, + CMS\CmsAddress::class, + CMS\CmsEmail::class, + CMS\CmsGroup::class, + CMS\CmsTag::class, + CMS\CmsArticle::class, + CMS\CmsComment::class, ]); for ($i = 2; $i < 10000; ++$i) { - $user = new CmsUser(); + $user = new CMS\CmsUser(); $user->status = 'developer'; $user->username = 'jwage' . $i; @@ -48,7 +48,7 @@ final class SimpleHydrationBench $this->entityManager->flush(); $this->entityManager->clear(); - $this->repository = $this->entityManager->getRepository(CmsUser::class); + $this->repository = $this->entityManager->getRepository(CMS\CmsUser::class); } public function benchHydration() From 5401cb5329e78545d2e2192865e971c3b297042b Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:46:50 +0200 Subject: [PATCH 20/33] Removed old `InsertPerformanceTest` (moved to benchmark) --- .../ORM/Performance/InsertPerformanceTest.php | 56 ------------------- 1 file changed, 56 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Performance/InsertPerformanceTest.php diff --git a/tests/Doctrine/Tests/ORM/Performance/InsertPerformanceTest.php b/tests/Doctrine/Tests/ORM/Performance/InsertPerformanceTest.php deleted file mode 100644 index db5455b06..000000000 --- a/tests/Doctrine/Tests/ORM/Performance/InsertPerformanceTest.php +++ /dev/null @@ -1,56 +0,0 @@ -useModelSet('cms'); - parent::setUp(); - } - - /** - * [romanb: 10000 objects in ~8 seconds] - */ - public function testInsertPerformance() - { - $s = microtime(true); - - $conn = $this->_em->getConnection(); - - $this->setMaxRunningTime(10); - - //echo "Memory usage before: " . (memory_get_usage() / 1024) . " KB" . PHP_EOL; - - $batchSize = 20; - for ($i=1; $i<=10000; ++$i) { - $user = new CmsUser; - $user->status = 'user'; - $user->username = 'user' . $i; - $user->name = 'Mr.Smith-' . $i; - $this->_em->persist($user); - if (($i % $batchSize) == 0) { - $this->_em->flush(); - $this->_em->clear(); - } - } - - //gc_collect_cycles(); - //echo "Memory usage after: " . (memory_get_usage() / 1024) . " KB" . PHP_EOL; - - $e = microtime(true); - - echo ' Inserted 10000 objects in ' . ($e - $s) . ' seconds' . PHP_EOL; - } -} - From 29f55eaef975e98ddd6785e1fcf5ceb8c22cd8b9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:50:59 +0200 Subject: [PATCH 21/33] Removing instantiation overhead from benchmark --- .../SimpleInsertPerformanceBench.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php index 5ab8906ed..68a933dd3 100644 --- a/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SimpleInsertPerformanceBench.php @@ -19,6 +19,11 @@ final class SimpleInsertPerformanceBench */ private $entityManager; + /** + * @var CMS\CmsUser[] + */ + private $users; + public function init() { $this->entityManager = EntityManagerFactory::getEntityManager([ @@ -31,11 +36,6 @@ final class SimpleInsertPerformanceBench CMS\CmsArticle::class, CMS\CmsComment::class, ]); - } - - public function benchHydration() - { - $batchSize = 20; for ($i = 1; $i <= 10000; ++$i) { $user = new CMS\CmsUser; @@ -43,9 +43,16 @@ final class SimpleInsertPerformanceBench $user->username = 'user' . $i; $user->name = 'Mr.Smith-' . $i; + $this->users[$i] = $user; + } + } + + public function benchHydration() + { + foreach ($this->users as $key => $user) { $this->entityManager->persist($user); - if (! ($i % $batchSize)) { + if (! ($key % 20)) { $this->entityManager->flush(); $this->entityManager->clear(); } From 2692435705413c7bed7040c2495532b036a6bda5 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 21:58:24 +0200 Subject: [PATCH 22/33] Benchmarking insert operations for a JTI --- .../InheritanceInsertPerformanceBench.php | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php b/tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php new file mode 100644 index 000000000..220ec5c01 --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php @@ -0,0 +1,100 @@ +entityManager = EntityManagerFactory::getEntityManager([ + Company\CompanyPerson::class, + Company\CompanyEmployee::class, + Company\CompanyManager::class, + Company\CompanyOrganization::class, + Company\CompanyEvent::class, + Company\CompanyAuction::class, + Company\CompanyRaffle::class, + Company\CompanyCar::class, + Company\CompanyContract::class, + ]); + + $person = new Company\CompanyEmployee(); + $person->setName('Poor Sales Guy'); + $person->setDepartment('Sales'); + $person->setSalary(100); + $this->entityManager->persist($person); + + for ($i = 0; $i < 33; $i++) { + $this->fixContracts[$i] = new Company\CompanyFixContract(); + $this->fixContracts[$i]->setFixPrice(1000); + $this->fixContracts[$i]->setSalesPerson($person); + $this->fixContracts[$i]->markCompleted(); + + $this->flexContracts[$i] = new Company\CompanyFlexContract(); + $this->flexContracts[$i]->setSalesPerson($person); + $this->flexContracts[$i]->setHoursWorked(100); + $this->flexContracts[$i]->setPricePerHour(100); + $this->flexContracts[$i]->markCompleted(); + + $this->ultraContracts[$i] = new Company\CompanyFlexUltraContract(); + $this->ultraContracts[$i]->setSalesPerson($person); + $this->ultraContracts[$i]->setHoursWorked(150); + $this->ultraContracts[$i]->setPricePerHour(150); + $this->ultraContracts[$i]->setMaxPrice(7000); + } + } + + public function benchInsertFixContracts() + { + array_map([$this->entityManager, 'persist'], $this->fixContracts); + $this->entityManager->flush(); + } + + public function benchInsertFlexContracts() + { + array_map([$this->entityManager, 'persist'], $this->flexContracts); + $this->entityManager->flush(); + } + + public function benchInsertUltraContracts() + { + array_map([$this->entityManager, 'persist'], $this->ultraContracts); + $this->entityManager->flush(); + } + + public function benchInsertAllContracts() + { + array_map([$this->entityManager, 'persist'], $this->fixContracts); + array_map([$this->entityManager, 'persist'], $this->flexContracts); + array_map([$this->entityManager, 'persist'], $this->ultraContracts); + $this->entityManager->flush(); + } +} From c5a636ebfbe4f6abd9ad9ddd2e28c5ab93c3b13c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:07:25 +0200 Subject: [PATCH 23/33] Corrected benchmark name: benchmark affects a STI --- ...nch.php => SingleTableInheritanceInsertPerformanceBench.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/Doctrine/Performance/Hydration/{InheritanceInsertPerformanceBench.php => SingleTableInheritanceInsertPerformanceBench.php} (98%) diff --git a/tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SingleTableInheritanceInsertPerformanceBench.php similarity index 98% rename from tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php rename to tests/Doctrine/Performance/Hydration/SingleTableInheritanceInsertPerformanceBench.php index 220ec5c01..8014b0ed1 100644 --- a/tests/Doctrine/Performance/Hydration/InheritanceInsertPerformanceBench.php +++ b/tests/Doctrine/Performance/Hydration/SingleTableInheritanceInsertPerformanceBench.php @@ -10,7 +10,7 @@ use PhpBench\Benchmark\Metadata\Annotations\BeforeMethods; /** * @BeforeMethods({"init"}) */ -final class InheritanceInsertPerformanceBench +final class SingleTableInheritanceInsertPerformanceBench { /** * @var EntityManagerInterface From 52402917a0d519daa44dc104cd7ae1521eff181c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:07:35 +0200 Subject: [PATCH 24/33] Benchmarking hydration of a STI --- ...leInheritanceHydrationPerformanceBench.php | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 tests/Doctrine/Performance/Hydration/SingleTableInheritanceHydrationPerformanceBench.php diff --git a/tests/Doctrine/Performance/Hydration/SingleTableInheritanceHydrationPerformanceBench.php b/tests/Doctrine/Performance/Hydration/SingleTableInheritanceHydrationPerformanceBench.php new file mode 100644 index 000000000..ec6c17c3e --- /dev/null +++ b/tests/Doctrine/Performance/Hydration/SingleTableInheritanceHydrationPerformanceBench.php @@ -0,0 +1,107 @@ +contractsRepository = $entityManager->getRepository(Company\CompanyContract::class); + $this->fixContractsRepository = $entityManager->getRepository(Company\CompanyFixContract::class); + $this->flexContractRepository = $entityManager->getRepository(Company\CompanyFlexContract::class); + $this->ultraContractRepository = $entityManager->getRepository(Company\CompanyFlexUltraContract::class); + + $person = new Company\CompanyEmployee(); + $person->setName('Poor Sales Guy'); + $person->setDepartment('Sales'); + $person->setSalary(100); + $entityManager->persist($person); + + for ($i = 0; $i < 33; $i++) { + $fixContract = new Company\CompanyFixContract(); + $flexContract = new Company\CompanyFlexContract(); + $ultraContract = new Company\CompanyFlexUltraContract(); + + $fixContract->setFixPrice(1000); + $fixContract->setSalesPerson($person); + $fixContract->markCompleted(); + + $flexContract->setSalesPerson($person); + $flexContract->setHoursWorked(100); + $flexContract->setPricePerHour(100); + $flexContract->markCompleted(); + + $ultraContract->setSalesPerson($person); + $ultraContract->setHoursWorked(150); + $ultraContract->setPricePerHour(150); + $ultraContract->setMaxPrice(7000); + + $entityManager->persist($fixContract); + $entityManager->persist($flexContract); + $entityManager->persist($ultraContract); + } + + $entityManager->flush(); + $entityManager->clear(); + } + + public function benchHydrateFixContracts() + { + $this->fixContractsRepository->findAll(); + } + + public function benchHydrateFlexContracts() + { + $this->flexContractRepository->findAll(); + } + + public function benchHydrateUltraContracts() + { + $this->ultraContractRepository->findAll(); + } + + public function benchHydrateAllContracts() + { + $this->contractsRepository->findAll(); + } +} From 8ec186f0957e9edc107d80b666b15b471dbd6d3a Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:10:20 +0200 Subject: [PATCH 25/33] Removing old inheritance persister test --- .../InheritancePersisterPerformanceTest.php | 69 ------------------- 1 file changed, 69 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Performance/InheritancePersisterPerformanceTest.php diff --git a/tests/Doctrine/Tests/ORM/Performance/InheritancePersisterPerformanceTest.php b/tests/Doctrine/Tests/ORM/Performance/InheritancePersisterPerformanceTest.php deleted file mode 100644 index 726389a4c..000000000 --- a/tests/Doctrine/Tests/ORM/Performance/InheritancePersisterPerformanceTest.php +++ /dev/null @@ -1,69 +0,0 @@ -useModelSet('company'); - parent::setUp(); - } - - public function testCompanyContract() - { - $person = new CompanyEmployee(); - $person->setName('Poor Sales Guy'); - $person->setDepartment('Sales'); - $person->setSalary(100); - $this->_em->persist($person); - - for ($i = 0; $i < 33; $i++) { - $fix = new CompanyFixContract(); - $fix->setFixPrice(1000); - $fix->setSalesPerson($person); - $fix->markCompleted(); - $this->_em->persist($fix); - - $flex = new CompanyFlexContract(); - $flex->setSalesPerson($person); - $flex->setHoursWorked(100); - $flex->setPricePerHour(100); - $flex->markCompleted(); - $this->_em->persist($flex); - - $ultra = new CompanyFlexUltraContract(); - $ultra->setSalesPerson($person); - $ultra->setHoursWorked(150); - $ultra->setPricePerHour(150); - $ultra->setMaxPrice(7000); - $this->_em->persist($ultra); - } - - $this->_em->flush(); - $this->_em->clear(); - - $start = microtime(true); - $contracts = $this->_em->getRepository(CompanyContract::class)->findAll(); - echo "99 CompanyContract: " . number_format(microtime(true) - $start, 6) . "\n"; - $this->assertEquals(99, count($contracts)); - - $this->_em->clear(); - - $start = microtime(true); - $contracts = $this->_em->getRepository(CompanyContract::class)->findAll(); - echo "99 CompanyContract: " . number_format(microtime(true) - $start, 6) . "\n"; - $this->assertEquals(99, count($contracts)); - } -} From 7515dd20f262e7c5a675c67b3a94f05e44691526 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:10:47 +0200 Subject: [PATCH 26/33] Removing old `PersisterPerformanceTest` --- .../Performance/PersisterPerformanceTest.php | 113 ------------------ 1 file changed, 113 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Performance/PersisterPerformanceTest.php diff --git a/tests/Doctrine/Tests/ORM/Performance/PersisterPerformanceTest.php b/tests/Doctrine/Tests/ORM/Performance/PersisterPerformanceTest.php deleted file mode 100644 index 30494d49b..000000000 --- a/tests/Doctrine/Tests/ORM/Performance/PersisterPerformanceTest.php +++ /dev/null @@ -1,113 +0,0 @@ -useModelSet('cms'); - parent::setUp(); - } - - public function testFindCmsArticle() - { - $author = new CmsUser(); - $author->name = "beberlei"; - $author->status = "active"; - $author->username = "beberlei"; - $this->_em->persist($author); - - $ids = []; - for ($i = 0; $i < 100; $i++) { - $article = new CmsArticle(); - $article->text = "foo"; - $article->topic = "bar"; - $article->user = $author; - $this->_em->persist($article); - $ids[] = $article; - } - $this->_em->flush(); - $this->_em->clear(); - - $start = microtime(true); - $articles = $this->_em->getRepository(CmsArticle::class)->findAll(); - echo "100 CmsArticle findAll(): " . number_format(microtime(true) - $start, 6) . "\n"; - - $this->_em->clear(); - - $start = microtime(true); - $articles = $this->_em->getRepository(CmsArticle::class)->findAll(); - echo "100 CmsArticle findAll(): " . number_format(microtime(true) - $start, 6) . "\n"; - - $this->_em->clear(); - - $start = microtime(true); - for ($i = 0; $i < 100; $i++) { - $articles = $this->_em->getRepository(CmsArticle::class)->find($ids[$i]->id); - } - echo "100 CmsArticle find(): " . number_format(microtime(true) - $start, 6) . "\n"; - - $this->_em->clear(); - - $start = microtime(true); - for ($i = 0; $i < 100; $i++) { - $articles = $this->_em->getRepository(CmsArticle::class)->find($ids[$i]->id); - } - echo "100 CmsArticle find(): " . number_format(microtime(true) - $start, 6) . "\n"; - } - - public function testFindCmsGroup() - { - for ($i = 0; $i < 100; $i++) { - $group = new CmsGroup(); - $group->name = "foo" . $i; - $this->_em->persist($group); - } - $this->_em->flush(); - $this->_em->clear(); - - $start = microtime(true); - $articles = $this->_em->getRepository(CmsGroup::class)->findAll(); - echo "100 CmsGroup: " . number_format(microtime(true) - $start, 6) . "\n"; - - $this->_em->clear(); - - $start = microtime(true); - $articles = $this->_em->getRepository(CmsGroup::class)->findAll(); - echo "100 CmsGroup: " . number_format(microtime(true) - $start, 6) . "\n"; - } - - public function testFindCmsUser() - { - for ($i = 0; $i < 100; $i++) { - $user = new CmsUser(); - $user->name = "beberlei"; - $user->status = "active"; - $user->username = "beberlei".$i; - $this->_em->persist($user); - } - - $this->_em->flush(); - $this->_em->clear(); - - $start = microtime(true); - $articles = $this->_em->getRepository(CmsUser::class)->findAll(); - echo "100 CmsUser: " . number_format(microtime(true) - $start, 6) . "\n"; - - $this->_em->clear(); - - $start = microtime(true); - $articles = $this->_em->getRepository(CmsUser::class)->findAll(); - echo "100 CmsUser: " . number_format(microtime(true) - $start, 6) . "\n"; - } -} From b1bbad3b15b10a39320d849b13674a570aa4db77 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:28:23 +0200 Subject: [PATCH 27/33] Unit of work changeset computation test --- .../UnitOfWorkComputeChangesBench.php | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/Doctrine/Performance/ChangeSet/UnitOfWorkComputeChangesBench.php diff --git a/tests/Doctrine/Performance/ChangeSet/UnitOfWorkComputeChangesBench.php b/tests/Doctrine/Performance/ChangeSet/UnitOfWorkComputeChangesBench.php new file mode 100644 index 000000000..25cc2fffd --- /dev/null +++ b/tests/Doctrine/Performance/ChangeSet/UnitOfWorkComputeChangesBench.php @@ -0,0 +1,73 @@ +unitOfWork = EntityManagerFactory::getEntityManager([])->getUnitOfWork(); + + for ($i = 1; $i <= 100; ++$i) { + $user = new CmsUser; + $user->id = $i; + $user->status = 'user'; + $user->username = 'user' . $i; + $user->name = 'Mr.Smith-' . $i; + $this->users[] = $user; + + $this->unitOfWork->registerManaged( + $user, + [ + 'id' => $i, + ], + [ + 'id' => $user->id, + 'status' => $user->status, + 'username' => $user->username, + 'name' => $user->name, + 'address' => $user->address, + 'email' => $user->email, + ] + ); + } + + $this->unitOfWork->computeChangeSets(); + + if ($this->unitOfWork->getScheduledEntityUpdates()) { + throw new \LogicException('Unit of work should be clean at this stage'); + } + + foreach ($this->users AS $user) { + $user->status = 'other'; + $user->username .= '++'; + $user->name = str_replace('Mr.', 'Mrs.', $user->name); + } + } + + public function benchChangeSetComputation() + { + $this->unitOfWork->computeChangeSets(); + } +} + From 77ce354f183674091dab9dca4363ba0b78bcfa0c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:28:54 +0200 Subject: [PATCH 28/33] Removing old `UnitOfWorkPerformanceTest` --- .../Performance/UnitOfWorkPerformanceTest.php | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Performance/UnitOfWorkPerformanceTest.php diff --git a/tests/Doctrine/Tests/ORM/Performance/UnitOfWorkPerformanceTest.php b/tests/Doctrine/Tests/ORM/Performance/UnitOfWorkPerformanceTest.php deleted file mode 100644 index 3d63eb4d8..000000000 --- a/tests/Doctrine/Tests/ORM/Performance/UnitOfWorkPerformanceTest.php +++ /dev/null @@ -1,50 +0,0 @@ -useModelSet('cms'); - parent::setUp(); - } - - public function testComputeChanges() - { - $n = 100; - - $users = []; - for ($i=1; $i<=$n; ++$i) { - $user = new CmsUser; - $user->status = 'user'; - $user->username = 'user' . $i; - $user->name = 'Mr.Smith-' . $i; - $this->_em->persist($user); - $users[] = $user; - } - $this->_em->flush(); - - - foreach ($users AS $user) { - $user->status = 'other'; - $user->username = $user->username . '++'; - $user->name = str_replace('Mr.', 'Mrs.', $user->name); - } - - $s = microtime(true); - $this->_em->flush(); - $e = microtime(true); - - echo ' Compute ChangeSet '.$n.' objects in ' . ($e - $s) . ' seconds' . PHP_EOL; - } -} From d658364b59309af8612ae03a170a58d8764aae53 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 22:38:02 +0200 Subject: [PATCH 29/33] Benchmarking instantiation of proxies --- .../ProxyInstantiationTimeBench.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/Doctrine/Performance/LazyLoading/ProxyInstantiationTimeBench.php diff --git a/tests/Doctrine/Performance/LazyLoading/ProxyInstantiationTimeBench.php b/tests/Doctrine/Performance/LazyLoading/ProxyInstantiationTimeBench.php new file mode 100644 index 000000000..da5a2c94f --- /dev/null +++ b/tests/Doctrine/Performance/LazyLoading/ProxyInstantiationTimeBench.php @@ -0,0 +1,40 @@ +proxyFactory = EntityManagerFactory::getEntityManager([])->getProxyFactory(); + } + + public function benchCmsUserInstantiation() + { + for ($i = 0; $i < 100000; ++$i) { + $this->proxyFactory->getProxy(CmsUser::class, ['id' => $i]); + } + } + + public function benchCmsEmployeeInstantiation() + { + for ($i = 0; $i < 100000; ++$i) { + $this->proxyFactory->getProxy(CmsEmployee::class, ['id' => $i]); + } + } +} + From d8140d700ac40d4d8d165a89ca8182ec5ab98c6c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 23:02:26 +0200 Subject: [PATCH 30/33] Benchmarking proxy initialization logic --- .../ProxyInitializationTimeBench.php | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/Doctrine/Performance/LazyLoading/ProxyInitializationTimeBench.php diff --git a/tests/Doctrine/Performance/LazyLoading/ProxyInitializationTimeBench.php b/tests/Doctrine/Performance/LazyLoading/ProxyInitializationTimeBench.php new file mode 100644 index 000000000..aeb5a1d2d --- /dev/null +++ b/tests/Doctrine/Performance/LazyLoading/ProxyInitializationTimeBench.php @@ -0,0 +1,81 @@ +getProxyFactory(); + + for ($i = 0; $i < 10000; ++$i) { + $this->cmsUsers[$i] = $proxyFactory->getProxy(CmsUser::class, ['id' => $i]); + $this->cmsEmployees[$i] = $proxyFactory->getProxy(CmsEmployee::class, ['id' => $i]); + $this->initializedUsers[$i] = $proxyFactory->getProxy(CmsUser::class, ['id' => $i]); + $this->initializedEmployees[$i] = $proxyFactory->getProxy(CmsEmployee::class, ['id' => $i]); + + $this->initializedUsers[$i]->__load(); + $this->initializedEmployees[$i]->__load(); + } + } + + public function benchCmsUserInitialization() + { + foreach ($this->cmsUsers as $proxy) { + $proxy->__load(); + } + } + + public function benchCmsEmployeeInitialization() + { + foreach ($this->cmsEmployees as $proxy) { + $proxy->__load(); + } + } + + public function benchInitializationOfAlreadyInitializedCmsUsers() + { + foreach ($this->initializedUsers as $proxy) { + $proxy->__load(); + } + } + + public function benchInitializationOfAlreadyInitializedCmsEmployees() + { + foreach ($this->initializedEmployees as $proxy) { + $proxy->__load(); + } + } +} + From f1bc1bbf12becd1cc46cc4e2f0636c6e28344969 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 23:02:44 +0200 Subject: [PATCH 31/33] Mocks required by the proxy performance benchmarks --- .../Performance/Mock/NonLoadingPersister.php | 31 ++ .../Mock/NonProxyLoadingEntityManager.php | 352 ++++++++++++++++++ .../Mock/NonProxyLoadingUnitOfWork.php | 31 ++ 3 files changed, 414 insertions(+) create mode 100644 tests/Doctrine/Performance/Mock/NonLoadingPersister.php create mode 100644 tests/Doctrine/Performance/Mock/NonProxyLoadingEntityManager.php create mode 100644 tests/Doctrine/Performance/Mock/NonProxyLoadingUnitOfWork.php diff --git a/tests/Doctrine/Performance/Mock/NonLoadingPersister.php b/tests/Doctrine/Performance/Mock/NonLoadingPersister.php new file mode 100644 index 000000000..35881c5a9 --- /dev/null +++ b/tests/Doctrine/Performance/Mock/NonLoadingPersister.php @@ -0,0 +1,31 @@ +realEntityManager = $realEntityManager; + } + + /** + * {@inheritDoc} + */ + public function getProxyFactory() + { + $config = $this->realEntityManager->getConfiguration(); + + return new ProxyFactory( + $this, + $config->getProxyDir(), + $config->getProxyNamespace(), + $config->getAutoGenerateProxyClasses() + ); + } + + /** + * {@inheritDoc} + */ + public function getMetadataFactory() + { + return $this->realEntityManager->getMetadataFactory(); + } + + /** + * {@inheritDoc} + */ + public function getClassMetadata($className) + { + return $this->realEntityManager->getClassMetadata($className); + } + + /** + * {@inheritDoc} + */ + public function getUnitOfWork() + { + return new NonProxyLoadingUnitOfWork(); + } + + /** + * {@inheritDoc} + */ + public function getCache() + { + return $this->realEntityManager->getCache(); + } + + /** + * {@inheritDoc} + */ + public function getConnection() + { + return $this->realEntityManager->getConnection(); + } + + /** + * {@inheritDoc} + */ + public function getExpressionBuilder() + { + return $this->realEntityManager->getExpressionBuilder(); + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + $this->realEntityManager->beginTransaction(); + } + + /** + * {@inheritDoc} + */ + public function transactional($func) + { + return $this->realEntityManager->transactional($func); + } + + /** + * {@inheritDoc} + */ + public function commit() + { + $this->realEntityManager->commit(); + } + + /** + * {@inheritDoc} + */ + public function rollback() + { + $this->realEntityManager->rollback(); + } + + /** + * {@inheritDoc} + */ + public function createQuery($dql = '') + { + return $this->realEntityManager->createQuery($dql); + } + + /** + * {@inheritDoc} + */ + public function createNamedQuery($name) + { + return $this->realEntityManager->createNamedQuery($name); + } + + /** + * {@inheritDoc} + */ + public function createNativeQuery($sql, ResultSetMapping $rsm) + { + return $this->realEntityManager->createNativeQuery($sql, $rsm); + } + + /** + * {@inheritDoc} + */ + public function createNamedNativeQuery($name) + { + return $this->realEntityManager->createNamedNativeQuery($name); + } + + /** + * {@inheritDoc} + */ + public function createQueryBuilder() + { + return $this->realEntityManager->createQueryBuilder(); + } + + /** + * {@inheritDoc} + */ + public function getReference($entityName, $id) + { + return $this->realEntityManager->getReference($entityName, $id); + } + + /** + * {@inheritDoc} + */ + public function getPartialReference($entityName, $identifier) + { + return $this->realEntityManager->getPartialReference($entityName, $identifier); + } + + /** + * {@inheritDoc} + */ + public function close() + { + $this->realEntityManager->close(); + } + + /** + * {@inheritDoc} + */ + public function copy($entity, $deep = false) + { + return $this->realEntityManager->copy($entity, $deep); + } + + /** + * {@inheritDoc} + */ + public function lock($entity, $lockMode, $lockVersion = null) + { + $this->realEntityManager->lock($entity, $lockMode, $lockVersion); + } + + /** + * {@inheritDoc} + */ + public function getEventManager() + { + return $this->realEntityManager->getEventManager(); + } + + /** + * {@inheritDoc} + */ + public function getConfiguration() + { + return $this->realEntityManager->getConfiguration(); + } + + /** + * {@inheritDoc} + */ + public function isOpen() + { + return $this->realEntityManager->isOpen(); + } + + /** + * {@inheritDoc} + */ + public function getHydrator($hydrationMode) + { + return $this->realEntityManager->getHydrator($hydrationMode); + } + + /** + * {@inheritDoc} + */ + public function newHydrator($hydrationMode) + { + return $this->realEntityManager->newHydrator($hydrationMode); + } + + /** + * {@inheritDoc} + */ + public function getFilters() + { + return $this->realEntityManager->getFilters(); + } + + /** + * {@inheritDoc} + */ + public function isFiltersStateClean() + { + return $this->realEntityManager->isFiltersStateClean(); + } + + /** + * {@inheritDoc} + */ + public function hasFilters() + { + return $this->realEntityManager->hasFilters(); + } + + /** + * {@inheritDoc} + */ + public function find($className, $id) + { + return $this->realEntityManager->find($className, $id); + } + + /** + * {@inheritDoc} + */ + public function persist($object) + { + $this->realEntityManager->persist($object); + } + + /** + * {@inheritDoc} + */ + public function remove($object) + { + $this->realEntityManager->remove($object); + } + + /** + * {@inheritDoc} + */ + public function merge($object) + { + return $this->realEntityManager->merge($object); + } + + /** + * {@inheritDoc} + */ + public function clear($objectName = null) + { + $this->realEntityManager->clear($objectName); + } + + /** + * {@inheritDoc} + */ + public function detach($object) + { + $this->realEntityManager->detach($object); + } + + /** + * {@inheritDoc} + */ + public function refresh($object) + { + $this->realEntityManager->refresh($object); + } + + /** + * {@inheritDoc} + */ + public function flush() + { + $this->realEntityManager->flush(); + } + + /** + * {@inheritDoc} + */ + public function getRepository($className) + { + return $this->realEntityManager->getRepository($className); + } + + /** + * {@inheritDoc} + */ + public function initializeObject($obj) + { + $this->realEntityManager->initializeObject($obj); + } + + /** + * {@inheritDoc} + */ + public function contains($object) + { + return $this->realEntityManager->contains($object); + } +} \ No newline at end of file diff --git a/tests/Doctrine/Performance/Mock/NonProxyLoadingUnitOfWork.php b/tests/Doctrine/Performance/Mock/NonProxyLoadingUnitOfWork.php new file mode 100644 index 000000000..dd9139ae7 --- /dev/null +++ b/tests/Doctrine/Performance/Mock/NonProxyLoadingUnitOfWork.php @@ -0,0 +1,31 @@ +entityPersister = new NonLoadingPersister(); + } + + /** + * {@inheritDoc} + */ + public function getEntityPersister($entityName) + { + return $this->entityPersister; + } +} From cfa9d787fedd0e76fb17c568dff8d251ac578ba6 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 26 May 2016 23:02:58 +0200 Subject: [PATCH 32/33] Removing old `ProxyPerformanceTest` --- .../ORM/Performance/ProxyPerformanceTest.php | 155 ------------------ 1 file changed, 155 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Performance/ProxyPerformanceTest.php diff --git a/tests/Doctrine/Tests/ORM/Performance/ProxyPerformanceTest.php b/tests/Doctrine/Tests/ORM/Performance/ProxyPerformanceTest.php deleted file mode 100644 index d73964dcc..000000000 --- a/tests/Doctrine/Tests/ORM/Performance/ProxyPerformanceTest.php +++ /dev/null @@ -1,155 +0,0 @@ - - * @group performance - */ -class ProxyPerformanceTest extends OrmPerformanceTestCase -{ - /** - * @return array - */ - public function entitiesProvider() - { - return [ - [CmsEmployee::class], - [CmsUser::class], - ]; - } - - /** - * @dataProvider entitiesProvider - */ - public function testProxyInstantiationPerformance($entityName) - { - $proxyFactory = $this->_getEntityManager()->getProxyFactory(); - $this->setMaxRunningTime(5); - $start = microtime(true); - - for ($i = 0; $i < 100000; $i += 1) { - $user = $proxyFactory->getProxy($entityName, ['id' => $i]); - } - - echo __FUNCTION__ . " - " . (microtime(true) - $start) . " seconds with " . $entityName . PHP_EOL; - } - - /** - * @dataProvider entitiesProvider - */ - public function testProxyForcedInitializationPerformance($entityName) - { - $em = new MockEntityManager($this->_getEntityManager()); - $proxyFactory = $em->getProxyFactory(); - /* @var $user \Doctrine\Common\Proxy\Proxy */ - $user = $proxyFactory->getProxy($entityName, ['id' => 1]); - $initializer = $user->__getInitializer(); - - $this->setMaxRunningTime(5); - $start = microtime(true); - - for ($i = 0; $i < 100000; $i += 1) { - $user->__setInitialized(false); - $user->__setInitializer($initializer); - $user->__load(); - $user->__load(); - } - - echo __FUNCTION__ . " - " . (microtime(true) - $start) . " seconds with " . $entityName . PHP_EOL; - } -} - -/** - * Mock entity manager to fake `getPersister()` - */ -class MockEntityManager extends EntityManager -{ - /** @var EntityManager */ - private $em; - - /** @param EntityManager $em */ - public function __construct(EntityManager $em) - { - $this->em = $em; - } - - /** {@inheritDoc} */ - public function getProxyFactory() - { - $config = $this->em->getConfiguration(); - - return new ProxyFactory( - $this, - $config->getProxyDir(), - $config->getProxyNamespace(), - $config->getAutoGenerateProxyClasses() - ); - } - - /** {@inheritDoc} */ - public function getMetadataFactory() - { - return $this->em->getMetadataFactory(); - } - - /** {@inheritDoc} */ - public function getClassMetadata($className) - { - return $this->em->getClassMetadata($className); - } - - /** {@inheritDoc} */ - public function getUnitOfWork() - { - return new MockUnitOfWork(); - } -} - -/** - * Mock UnitOfWork manager to fake `getPersister()` - */ -class MockUnitOfWork extends UnitOfWork -{ - /** @var PersisterMock */ - private $entityPersister; - - /** */ - public function __construct() - { - $this->entityPersister = new PersisterMock(); - } - - /** {@inheritDoc} */ - public function getEntityPersister($entityName) - { - return $this->entityPersister; - } -} - -/** - * Mock persister (we don't want PHPUnit comparator API to play a role in here) - */ -class PersisterMock extends BasicEntityPersister -{ - /** */ - public function __construct() - { - } - - /** {@inheritDoc} */ - public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = 0, $limit = null, array $orderBy = null) - { - return $entity; - } -} From e07c90df4488b7b44494695e46c3505f5cf21266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Sun, 23 Jul 2017 10:11:43 +0200 Subject: [PATCH 33/33] Add PHPBench to Travis-CI matrix Also separating the execution of the tests from other tools. --- .travis.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 57b2cb1f6..20c2aa3af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,11 +22,13 @@ before_script: - if [[ $PHPSTAN = 1 ]]; then composer require --dev --prefer-stable phpstan/phpstan:^0.7 symfony/console:^3.0; fi - if [ "$MYSQL_VERSION" == "5.7" ]; then bash ./tests/travis/install-mysql-5.7.sh; fi; - if [[ $DB == "mysql" || $DB == "mariadb" ]]; then mysql -e "CREATE SCHEMA doctrine_tests; GRANT ALL PRIVILEGES ON doctrine_tests.* to travis@'%'"; fi; + - if [[ $PHPBENCH = 1 ]]; then wget https://phpbench.github.io/phpbench/phpbench.phar https://phpbench.github.io/phpbench/phpbench.phar.pubkey; fi script: - if [[ $PHPSTAN = 1 ]]; then vendor/bin/phpstan analyse -l 1 -c phpstan.neon lib; fi - - ENABLE_SECOND_LEVEL_CACHE=0 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml $PHPUNIT_FLAGS - - ENABLE_SECOND_LEVEL_CACHE=1 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --exclude-group performance,non-cacheable,locking_functional + - if [[ $PHPBENCH = 1 ]]; then php phpbench.phar run -l dots --report=default; fi + - if [[ $DB != "none" ]]; then ENABLE_SECOND_LEVEL_CACHE=0 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml $PHPUNIT_FLAGS; fi + - if [[ $DB != "none" ]]; then ENABLE_SECOND_LEVEL_CACHE=1 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --exclude-group performance,non-cacheable,locking_functional; fi after_script: - if [[ "$PHPUNIT_FLAGS" != "" ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi @@ -39,14 +41,15 @@ matrix: env: DB=mariadb addons: mariadb: 10.1 + - php: 7.1 env: - DB=sqlite - DEPENDENCIES='low' + - php: 7.1 env: - DB=pgsql - - PHPSTAN=1 - php: 7.1 env: DB=mysql MYSQL_VERSION=5.7 @@ -55,6 +58,15 @@ matrix: env: DB=mysql MYSQL_VERSION=5.7 sudo: required + - php: 7.1 + env: + - DB=none + - PHPSTAN=1 + - php: 7.1 + env: + - DB=none + - PHPBENCH=1 + allow_failures: - php: nightly