3 namespace Doctrine\Tests\ORM\Performance;
5 require_once __DIR__ . '/../../TestInit.php';
7 use Doctrine\Tests\Mocks\HydratorMockStatement,
8 Doctrine\ORM\Query\ResultSetMapping,
12 * Tests to prevent serious performance regressions.
14 * IMPORTANT: Be sure to run these tests withoug xdebug or similar tools that
15 * seriously degrade performance.
20 class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
23 * Times for comparison:
25 * [romanb: 10000 rows => 0.7 seconds]
27 * MAXIMUM TIME: 1 second
29 public function testSimpleQueryScalarHydrationPerformance10000Rows()
31 $rsm = new ResultSetMapping;
32 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
33 $rsm->addFieldResult('u', 'u__id', 'id');
34 $rsm->addFieldResult('u', 'u__status', 'status');
35 $rsm->addFieldResult('u', 'u__username', 'username');
36 $rsm->addFieldResult('u', 'u__name', 'name');
43 'u__status' => 'developer',
44 'u__username' => 'romanb',
49 'u__status' => 'developer',
50 'u__username' => 'romanb',
55 'u__status' => 'developer',
56 'u__username' => 'romanb',
61 for ($i = 4; $i < 10000; ++$i) {
64 'u__status' => 'developer',
65 'u__username' => 'jwage',
66 'u__name' => 'Jonathan',
70 $stmt = new HydratorMockStatement($resultSet);
71 $hydrator = new \Doctrine\ORM\Internal\Hydration\ScalarHydrator($this->_em);
73 $this->setMaxRunningTime(1);
75 $result = $hydrator->hydrateAll($stmt, $rsm);
77 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
81 * Times for comparison:
83 * [romanb: 10000 rows => 1 second]
85 * MAXIMUM TIME: 2 seconds
87 public function testSimpleQueryArrayHydrationPerformance10000Rows()
89 $rsm = new ResultSetMapping;
90 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
91 $rsm->addFieldResult('u', 'u__id', 'id');
92 $rsm->addFieldResult('u', 'u__status', 'status');
93 $rsm->addFieldResult('u', 'u__username', 'username');
94 $rsm->addFieldResult('u', 'u__name', 'name');
101 'u__status' => 'developer',
102 'u__username' => 'romanb',
103 'u__name' => 'Roman',
107 'u__status' => 'developer',
108 'u__username' => 'romanb',
109 'u__name' => 'Roman',
113 'u__status' => 'developer',
114 'u__username' => 'romanb',
115 'u__name' => 'Roman',
119 for ($i = 4; $i < 10000; ++$i) {
120 $resultSet[] = array(
122 'u__status' => 'developer',
123 'u__username' => 'jwage',
124 'u__name' => 'Jonathan',
128 $stmt = new HydratorMockStatement($resultSet);
129 $hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
131 $this->setMaxRunningTime(2);
132 $s = microtime(true);
133 $result = $hydrator->hydrateAll($stmt, $rsm);
134 $e = microtime(true);
135 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
139 * Times for comparison:
141 * [romanb: 10000 rows => 1.4 seconds]
143 * MAXIMUM TIME: 3 seconds
145 public function testMixedQueryFetchJoinArrayHydrationPerformance10000Rows()
147 $rsm = new ResultSetMapping;
148 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
149 $rsm->addJoinedEntityResult(
150 'Doctrine\Tests\Models\CMS\CmsPhonenumber',
155 $rsm->addFieldResult('u', 'u__id', 'id');
156 $rsm->addFieldResult('u', 'u__status', 'status');
157 $rsm->addFieldResult('u', 'u__username', 'username');
158 $rsm->addFieldResult('u', 'u__name', 'name');
159 $rsm->addScalarResult('sclr0', 'nameUpper');
160 $rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber');
167 'u__status' => 'developer',
168 'u__username' => 'romanb',
169 'u__name' => 'Roman',
171 'p__phonenumber' => '42',
175 'u__status' => 'developer',
176 'u__username' => 'romanb',
177 'u__name' => 'Roman',
179 'p__phonenumber' => '43',
183 'u__status' => 'developer',
184 'u__username' => 'romanb',
185 'u__name' => 'Roman',
187 'p__phonenumber' => '91'
191 for ($i = 4; $i < 10000; ++$i) {
192 $resultSet[] = array(
194 'u__status' => 'developer',
195 'u__username' => 'jwage',
196 'u__name' => 'Jonathan',
197 'sclr0' => 'JWAGE' . $i,
198 'p__phonenumber' => '91'
202 $stmt = new HydratorMockStatement($resultSet);
203 $hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
205 $this->setMaxRunningTime(3);
206 $s = microtime(true);
207 $result = $hydrator->hydrateAll($stmt, $rsm);
208 $e = microtime(true);
209 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
213 * [romanb: 10000 rows => 1.5 seconds]
215 * MAXIMUM TIME: 3 seconds
217 public function testSimpleQueryPartialObjectHydrationPerformance10000Rows()
219 $rsm = new ResultSetMapping;
220 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
221 $rsm->addFieldResult('u', 'u__id', 'id');
222 $rsm->addFieldResult('u', 'u__status', 'status');
223 $rsm->addFieldResult('u', 'u__username', 'username');
224 $rsm->addFieldResult('u', 'u__name', 'name');
231 'u__status' => 'developer',
232 'u__username' => 'romanb',
233 'u__name' => 'Roman',
237 'u__status' => 'developer',
238 'u__username' => 'romanb',
239 'u__name' => 'Roman',
243 'u__status' => 'developer',
244 'u__username' => 'romanb',
245 'u__name' => 'Roman',
249 for ($i = 4; $i < 10000; ++$i) {
250 $resultSet[] = array(
252 'u__status' => 'developer',
253 'u__username' => 'jwage',
254 'u__name' => 'Jonathan',
258 $stmt = new HydratorMockStatement($resultSet);
259 $hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
261 $this->setMaxRunningTime(3);
262 $s = microtime(true);
263 $result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
264 $e = microtime(true);
265 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
269 * [romanb: 10000 rows => 3 seconds]
271 * MAXIMUM TIME: 4.5 seconds
273 public function testSimpleQueryFullObjectHydrationPerformance10000Rows()
275 $rsm = new ResultSetMapping;
276 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
277 $rsm->addFieldResult('u', 'u__id', 'id');
278 $rsm->addFieldResult('u', 'u__status', 'status');
279 $rsm->addFieldResult('u', 'u__username', 'username');
280 $rsm->addFieldResult('u', 'u__name', 'name');
281 $rsm->addJoinedEntityResult(
282 'Doctrine\Tests\Models\CMS\CmsAddress',
287 $rsm->addFieldResult('a', 'a__id', 'id');
288 //$rsm->addFieldResult('a', 'a__country', 'country');
289 //$rsm->addFieldResult('a', 'a__zip', 'zip');
290 //$rsm->addFieldResult('a', 'a__city', 'city');
297 'u__status' => 'developer',
298 'u__username' => 'romanb',
299 'u__name' => 'Roman',
304 for ($i = 2; $i < 10000; ++$i) {
305 $resultSet[] = array(
307 'u__status' => 'developer',
308 'u__username' => 'jwage',
309 'u__name' => 'Jonathan',
314 $stmt = new HydratorMockStatement($resultSet);
315 $hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
317 $this->setMaxRunningTime(5);
318 $s = microtime(true);
319 $result = $hydrator->hydrateAll($stmt, $rsm);
320 $e = microtime(true);
321 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
325 * [romanb: 2000 rows => 0.4 seconds]
327 * MAXIMUM TIME: 1 second
329 public function testMixedQueryFetchJoinPartialObjectHydrationPerformance2000Rows()
331 $rsm = new ResultSetMapping;
332 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
333 $rsm->addJoinedEntityResult(
334 'Doctrine\Tests\Models\CMS\CmsPhonenumber',
339 $rsm->addFieldResult('u', 'u__id', 'id');
340 $rsm->addFieldResult('u', 'u__status', 'status');
341 $rsm->addFieldResult('u', 'u__username', 'username');
342 $rsm->addFieldResult('u', 'u__name', 'name');
343 $rsm->addScalarResult('sclr0', 'nameUpper');
344 $rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber');
351 'u__status' => 'developer',
352 'u__username' => 'romanb',
353 'u__name' => 'Roman',
355 'p__phonenumber' => '42',
359 'u__status' => 'developer',
360 'u__username' => 'romanb',
361 'u__name' => 'Roman',
363 'p__phonenumber' => '43',
367 'u__status' => 'developer',
368 'u__username' => 'romanb',
369 'u__name' => 'Roman',
371 'p__phonenumber' => '91'
375 for ($i = 4; $i < 2000; ++$i) {
376 $resultSet[] = array(
378 'u__status' => 'developer',
379 'u__username' => 'jwage',
380 'u__name' => 'Jonathan',
381 'sclr0' => 'JWAGE' . $i,
382 'p__phonenumber' => '91'
386 $stmt = new HydratorMockStatement($resultSet);
387 $hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
389 $this->setMaxRunningTime(1);
390 $s = microtime(true);
391 $result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
392 $e = microtime(true);
393 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
397 * [romanb: 2000 rows => 0.6 seconds]
399 * MAXIMUM TIME: 1 second
401 public function testMixedQueryFetchJoinFullObjectHydrationPerformance2000Rows()
403 $rsm = new ResultSetMapping;
404 $rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
405 $rsm->addJoinedEntityResult(
406 'Doctrine\Tests\Models\CMS\CmsPhonenumber',
411 $rsm->addFieldResult('u', 'u__id', 'id');
412 $rsm->addFieldResult('u', 'u__status', 'status');
413 $rsm->addFieldResult('u', 'u__username', 'username');
414 $rsm->addFieldResult('u', 'u__name', 'name');
415 $rsm->addScalarResult('sclr0', 'nameUpper');
416 $rsm->addFieldResult('p', 'p__phonenumber', 'phonenumber');
417 $rsm->addJoinedEntityResult(
418 'Doctrine\Tests\Models\CMS\CmsAddress',
423 $rsm->addFieldResult('a', 'a__id', 'id');
430 'u__status' => 'developer',
431 'u__username' => 'romanb',
432 'u__name' => 'Roman',
434 'p__phonenumber' => '42',
439 for ($i = 2; $i < 2000; ++$i) {
440 $resultSet[] = array(
442 'u__status' => 'developer',
443 'u__username' => 'jwage',
444 'u__name' => 'Jonathan',
445 'sclr0' => 'JWAGE' . $i,
446 'p__phonenumber' => '91',
451 $stmt = new HydratorMockStatement($resultSet);
452 $hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
454 $this->setMaxRunningTime(1);
455 $s = microtime(true);
456 $result = $hydrator->hydrateAll($stmt, $rsm);
457 $e = microtime(true);
458 echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;