doctrine / orm

Doctrine Object Relational Mapper (ORM)
https://www.doctrine-project.org/projects/orm.html
MIT License
9.86k stars 2.5k forks source link

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

Closed arkhamvm closed 1 month ago

arkhamvm commented 1 month ago

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.

beberlei commented 1 month ago

Sounds like an xdebug problem and not a Doctrine one

arkhamvm commented 1 month ago

@beberlei maybe. But in my 10+ years of php/web development, Doctrine/ORM is the first library that causes this problem. And it's sounds easier to make changes in Doctrine, then in xdebug...

beberlei commented 1 month ago

Doctrine is not going to change its code when something else is causing problems