getSingleScalarResult: Enormous memory (100 MB+) and time usage if xdebug enabled #7361

Open
opened 2026-01-22 15:50:39 +01:00 by admin · 0 comments
Owner

Originally created by @arkhamvm on GitHub (May 4, 2024).

Bug Report

Q A
BC Break no
Version 3.0

PHP 8.3.6 (FROM php:8.3.6-fpm)
Xdebug v3.3.2

Summary

$queryBuilder = $this->users_ORMRepository->createQueryBuilder('u');
$queryBuilder
    ->select('u.inner_id')
    ->where('u.guid = :guid')
    ->setParameter('guid', $guid->toString())
;

try{
    return $queryBuilder->getQuery()->getSingleScalarResult();
} catch (NoResultException) {
    return null;
}

Current behavior

If NoResultException is thrown in SingleScalarHydrator::hydrateAllData it will cause xdebug stuck at AbstractHydrator::hydrateAll:

try {
    $result = $this->hydrateAllData();
    // Time and memory lag here. After hydrate method, but before "finally" is called
} finally { 
    $this->cleanup();
}

image

In my project it is around 150 MB of memory and 5 seconds of time.
At second similar call it consumes 800 MB of memory and 30 seconds.

It is absolutly accurate that memory usage caused by try/finally in SingleScalarHydrator.
Because this code will have no additional memory allocations:

$queryBuilder = $this->users_ORMRepository->createQueryBuilder('u');
$queryBuilder
    ->select('u.inner_id')
    ->where('u.guid = :guid')
    ->setParameter('guid', $guid->toString())
;

$userId = $queryBuilder->getQuery()->getOneOrNullResult();
if (null === $userId) {
    return null;
}

return $userId['inner_id'];

How to reproduce

Call getSingleScalarResult with query that returns NoResultException with xdebug enabled.

XDebug Config:

zend_extension=xdebug.so
[xdebug]
xdebug.mode = debug,develop,profile
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
xdebug.output_dir = /var/www/xdebug
xdebug.idekey = PHPSTORM
xdebug.dump_globals = 0
xdebug.collect_return = 1

xdebug.var_display_max_children = 100
xdebug.var_display_max_data = 500
xdebug.var_display_max_depth = 30
xdebug.max_nesting_level = 500
xdebug.overload_var_dump = 0

Expected behavior

No additional memory allocations.

Originally created by @arkhamvm on GitHub (May 4, 2024). ### Bug Report | Q | A |------------ | ------ | BC Break | no | Version | 3.0 PHP 8.3.6 (FROM php:8.3.6-fpm) Xdebug v3.3.2 #### Summary ```php $queryBuilder = $this->users_ORMRepository->createQueryBuilder('u'); $queryBuilder ->select('u.inner_id') ->where('u.guid = :guid') ->setParameter('guid', $guid->toString()) ; try{ return $queryBuilder->getQuery()->getSingleScalarResult(); } catch (NoResultException) { return null; } ``` #### Current behavior If `NoResultException` is thrown in `SingleScalarHydrator::hydrateAllData` it will cause xdebug stuck at `AbstractHydrator::hydrateAll`: ```php try { $result = $this->hydrateAllData(); // Time and memory lag here. After hydrate method, but before "finally" is called } finally { $this->cleanup(); } ``` ![image](https://github.com/doctrine/orm/assets/9816112/db2f43b7-89b0-4633-91b4-4bc9c11ea9b4) In my project it is around 150 MB of memory and 5 seconds of time. At second similar call it consumes 800 MB of memory and 30 seconds. It is absolutly accurate that memory usage caused by `try/finally` in `SingleScalarHydrator`. Because this code will have no additional memory allocations: ```php $queryBuilder = $this->users_ORMRepository->createQueryBuilder('u'); $queryBuilder ->select('u.inner_id') ->where('u.guid = :guid') ->setParameter('guid', $guid->toString()) ; $userId = $queryBuilder->getQuery()->getOneOrNullResult(); if (null === $userId) { return null; } return $userId['inner_id']; ``` #### How to reproduce Call `getSingleScalarResult` with query that returns `NoResultException` with `xdebug` enabled. XDebug Config: ``` zend_extension=xdebug.so [xdebug] xdebug.mode = debug,develop,profile xdebug.start_with_request = yes xdebug.client_host = host.docker.internal xdebug.client_port = 9003 xdebug.output_dir = /var/www/xdebug xdebug.idekey = PHPSTORM xdebug.dump_globals = 0 xdebug.collect_return = 1 xdebug.var_display_max_children = 100 xdebug.var_display_max_data = 500 xdebug.var_display_max_depth = 30 xdebug.max_nesting_level = 500 xdebug.overload_var_dump = 0 ``` #### Expected behavior No additional memory allocations.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7361