php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80447 Strange out of memory error when running with JIT
Submitted: 2020-11-30 20:21 UTC Modified: 2020-12-01 13:49 UTC
From: dac514 at hotmail dot com Assigned: dmitry (profile)
Status: Closed Package: JIT
PHP Version: 8.0.0 OS: Ubuntu
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: dac514 at hotmail dot com
New email:
PHP Version: OS:

 

 [2020-11-30 20:21 UTC] dac514 at hotmail dot com
Description:
------------
In the last few days benchmarksgame-team.pages.debian.net upgraded to PHP8.

This script;

https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/binarytrees-php-4.html

When run with JIT:

`/opt/src/php-8.0.0/bin/php -dzend_extension=/opt/src/php-8.0.0/lib/php/extensions/no-debug-non-zts-20200930/opcache.so -dopcache.enable_cli=1 -dopcache.jit_buffer_size=64M -n -d memory_limit=4096M binarytrees.php-4.php 21`

Runs out of memory, very unusually, (it did not run out of memory in previous versions of PHP)

The following weird hack is a workaround, change:

```
function createTree($depth)
{
    if (!$depth) {
        return [null, null];

```

To:

```
function createTree($depth)
{
    echo '';
    if (!$depth) {
        return [null, null];
```

I don't get it?


Test script:
---------------
function createTree($depth)
{
    // echo ''; // TODO: This hack works?!
    if (!$depth) {
        return [null, null];
    }
    $depth--;

    return [
        createTree($depth),
        createTree($depth)
    ];
}

function checkTree($treeNode)
{
    return 1
        + ($treeNode[0][0] === null ? 1 : checkTree($treeNode[0]))
        + ($treeNode[1][0] === null ? 1 : checkTree($treeNode[1]));
}

$minDepth = 4;
$n = ($argc == 2) ? $argv[1] : 1;
$maxDepth = max($minDepth + 2, $n);
$stretchDepth = $maxDepth + 1;

$stretchTree = createTree($stretchDepth);
echo "stretch tree of depth $stretchDepth\t check: ", checkTree($stretchTree), PHP_EOL;
unset($stretchTree);

$longLivedTree = createTree($maxDepth);

function startWorker($depth, $iter, $n, $size, $shmId)
{
    $pid = pcntl_fork();
    if ($pid) {
        return $pid;
    } else {
        $check = 0;
        for ($i = 1; $i <= $iter; ++$i) {
            $t = createTree($depth);
            $check += checkTree($t);
            unset($t);
        }
        $result = "$iter\t trees of depth $depth\t check: $check\n";
        shmop_write($shmId, $result, $size * ($n - 1));
        exit(0);
    }
}

$iterations = 1 << ($maxDepth);
$depthIterations = [$minDepth => $iterations];
do {
    $minDepth += 2;
    if ($minDepth <= $maxDepth) {
        $iterations >>= 2;
        $depthIterations[$minDepth] = $iterations;
    }
} while ($minDepth <= $maxDepth);

extension_loaded('shmop') or dl('shmop.so');
$size = 128;
$shmId = shmop_open(ftok(__FILE__, 'b'), 'c', 0644, $size * (count($depthIterations) + 1));
$PIDs = [];
$n = 0;
foreach ($depthIterations as $d => $i) {
    $PIDs[] = startWorker($d, $i, ++$n, $size, $shmId);
}
foreach ($PIDs as $PID) {
    pcntl_waitpid($PID, $status);
}
foreach (range(1, count($depthIterations)) as $n) {
    echo trim(shmop_read($shmId, $size * ($n - 1), $size)), PHP_EOL;
}
shmop_delete($shmId);

echo "long lived tree of depth $maxDepth\t check: ", checkTree($longLivedTree), PHP_EOL;

Expected result:
----------------
PROGRAM OUTPUT:
stretch tree of depth 22	 check: 8388607
2097152	 trees of depth 4	 check: 65011712
524288	 trees of depth 6	 check: 66584576
131072	 trees of depth 8	 check: 66977792
32768	 trees of depth 10	 check: 67076096
8192	 trees of depth 12	 check: 67100672
2048	 trees of depth 14	 check: 67106816
512	 trees of depth 16	 check: 67108352
128	 trees of depth 18	 check: 67108736
32	 trees of depth 20	 check: 67108832
long lived tree of depth 21	 check: 4194303

Actual result:
--------------
Out of memory error. Terminated.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-11-30 20:23 UTC] dac514 at hotmail dot com
Upstream ticket: https://salsa.debian.org/benchmarksgame-team/benchmarksgame/-/issues/401
 [2020-11-30 20:24 UTC] cmb@php.net
-Package: Unknown/Other Function +Package: JIT
 [2020-12-01 10:54 UTC] nikic@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: dmitry
 [2020-12-01 13:47 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=44475e70e2d29c862c58827ae72975205123b4a2
Log: Fixed bug #80447 (Strange out of memory error when running with JIT)
 [2020-12-01 13:47 UTC] dmitry@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 17:01:29 2024 UTC