57

I'm need to check if memory_limit is at least 64M in my script installer. This is just part of PHP code that should work, but probably due to this "M" it's not reading properly the value. How to fix this ?

  //memory_limit
    echo "<phpmem>";
    if(key_exists('PHP Core', $phpinfo))
    {
        if(key_exists('memory_limit', $phpinfo['PHP Core']))
        {
            $t=explode(".", $phpinfo['PHP Core']['memory_limit']);
            if($t[0]>=64)
                $ok=1;
            else
                $ok=0;
            echo "<val>{$phpinfo['PHP Core']['memory_limit']}</val><ok>$ok</ok>";
        }
        else
           echo "<val></val><ok>0</ok>";
    }
    else
        echo "<val></val><ok>0</ok>";
    echo "</phpmem>\n"; 
hakre
  • 193,403
  • 52
  • 435
  • 836
Spacedust
  • 931
  • 1
  • 11
  • 22

9 Answers9

92

Checking on command line:

php -i | grep "memory_limit"
Okan
  • 1,133
  • 8
  • 15
  • 3
    Are you able to explain the output I get from this: memory_limit => -1 => -1 – Ron Piggott Apr 21 '19 at 18:19
  • 1
    For some PHP settings -1 means "no limit" but I'm not sure about memory_limit. You can check it from your php.ini file. Execute php -i | grep "php.ini" on command line and check memory_limit in your Loaded Configuration File. – Okan Apr 22 '19 at 16:18
  • 2
    If terminal print => -1 => -1 this indicate memory limit is unlimited – Fernando León May 22 '20 at 17:19
49

Try to convert the value first (eg: 64M -> 64 * 1024 * 1024). After that, do comparison and print the result.

<?php
$memory_limit = ini_get('memory_limit');
if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) {
    if ($matches[2] == 'M') {
        $memory_limit = $matches[1] * 1024 * 1024; // nnnM -> nnn MB
    } else if ($matches[2] == 'K') {
        $memory_limit = $matches[1] * 1024; // nnnK -> nnn KB
    }
}

$ok = ($memory_limit >= 64 * 1024 * 1024); // at least 64M?

echo '<phpmem>';
echo '<val>' . $memory_limit . '</val>';
echo '<ok>' . ($ok ? 1 : 0) . '</ok>';
echo '</phpmem>';

Please note that the above code is just an idea. Don't forget to handle -1 (no memory limit), integer-only value (value in bytes), G (value in gigabytes), k/m/g (value in kilobytes, megabytes, gigabytes because shorthand is case-insensitive), etc.

Muhammad Alvin
  • 1,190
  • 9
  • 9
28

1. PHP-CLI:

Command line to check ini:

$ php -r "echo ini_get('memory_limit');"

Or check php-cli info and grep memory_limit value:

$ php -i | grep "memory_limit"

2. PHP-FPM:

Paste this line into index.php or any php file that can be viewed on a browser, then check the result:

<?php echo ini_get('memory_limit');

An alternative way is using phpinfo():

<?php phpinfo();

then find for memory_limit value enter image description here

Jared Chu
  • 2,757
  • 4
  • 27
  • 38
  • 6
    FYI this returns the memory limit for the CLI version of PHP, but your nginx/apache will use the "other" PHP process, the `fpm`version of PHP (sorry no idea who to describe this). Better check manually in both .ini: `/etc/php/7.4/cli/php.ini` and `/etc/php/7.4/fpm/php.ini` – Sliq Oct 12 '20 at 22:26
16

Here is another simpler way to check that.

$memory_limit = return_bytes(ini_get('memory_limit'));
if ($memory_limit < (64 * 1024 * 1024)) {
    // Memory insufficient      
}

/**
* Converts shorthand memory notation value to bytes
* From http://php.net/manual/en/function.ini-get.php
*
* @param $val Memory size shorthand notation string
*/
function return_bytes($val) {
    $val = trim($val);
    $last = strtolower($val[strlen($val)-1]);
    $val = substr($val, 0, -1);
    switch($last) {
        // The 'G' modifier is available since PHP 5.1.0
        case 'g':
            $val *= 1024;
        case 'm':
            $val *= 1024;
        case 'k':
            $val *= 1024;
    }
    return $val;
}
Ulver
  • 905
  • 8
  • 13
  • 2
    what about this? `$bytes = (int)$mem * 1024 ** ['k' => 1, 'm' => 2, 'g' => 3][strtolower($mem)[-1]] ?? 0;` – kaluzki Jul 05 '19 at 13:48
8

very old post. but i'll just leave this here:

/* converts a number with byte unit (B / K / M / G) into an integer */
function unitToInt($s)
{
    return (int)preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
        return $m[1] * pow(1024, strpos('BKMG', $m[2]));
    }, strtoupper($s));
}

$mem_limit = unitToInt(ini_get('memory_limit'));
Robbie
  • 17,605
  • 4
  • 35
  • 72
Gibz
  • 89
  • 1
  • 2
4

As long as your array $phpinfo['PHP Core']['memory_limit'] contains the value of memory_limit, it does work the following:

  • The last character of that value can signal the shorthand notation. If it's an invalid one, it's ignored.
  • The beginning of the string is converted to a number in PHP's own specific way: Whitespace ignored etc.
  • The text between the number and the shorthand notation (if any) is ignored.

Example:

# Memory Limit equal or higher than 64M?
$ok = (int) (bool) setting_to_bytes($phpinfo['PHP Core']['memory_limit']) >= 0x4000000;

/**
 * @param string $setting
 *
 * @return NULL|number
 */
function setting_to_bytes($setting)
{
    static $short = array('k' => 0x400,
                          'm' => 0x100000,
                          'g' => 0x40000000);

    $setting = (string)$setting;
    if (!($len = strlen($setting))) return NULL;
    $last    = strtolower($setting[$len - 1]);
    $numeric = (int) $setting;
    $numeric *= isset($short[$last]) ? $short[$last] : 1;
    return $numeric;
}

Details of the shorthand notation are outline in a PHP manual's FAQ entry and extreme details are part of Protocol of some PHP Memory Stretching Fun.

Take care if the setting is -1 PHP won't limit here, but the system does. So you need to decide how the installer treats that value.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • This is compact code, but it breaks under PHP 7.1+: `$numeric = 0 + $setting;` throws an exception because $setting is not a numeric value because of the suffix (message is " A non well formed numeric value encountered in [...]"). in (at least) 7.2, the following works instead: `$numeric = (int)$setting;` – Gabriel Magana Oct 14 '17 at 13:54
  • @GabrielMagana: Good point, it's quite some time ago I wrote that, and using (int) cast is prefereable over 0 + anyways for converting the number. Edited the answer. – hakre Oct 14 '17 at 23:11
4

Not so exact but simpler solution:

$limit = str_replace(array('G', 'M', 'K'), array('000000000', '000000', '000'), ini_get('memory_limit'));
if($limit < 500000000) ini_set('memory_limit', '500M');                     
Rauli Rajande
  • 2,010
  • 1
  • 20
  • 24
  • If you treat K as 2^10 it won't work. So it is not very universal. But thumb up for an invention. – elixon Aug 08 '19 at 15:21
  • Works quite well, because in the second line comparison you can have the same simplification. By now this works for me at a few hundred websites with image modifying plugin - the needed amount of memory is never very exact, so I check for 30% bigger number anyway and then the difference between 1024 and 1000 is just a rounding error :) – Rauli Rajande Aug 10 '19 at 14:03
4

If you are interested in CLI memory limit:

cat /etc/php/[7.0]/cli/php.ini | grep "memory_limit"

FPM / "Normal"

cat /etc/php/[7.0]/fpm/php.ini | grep "memory_limit"
OZZIE
  • 6,609
  • 7
  • 55
  • 59
2

Thank you for inspiration.

I had the same problem and instead of just copy-pasting some function from the Internet, I wrote an open source tool for it. Feel free to use it or provide feedback!

https://github.com/BrandEmbassy/php-memory

Just install it using Composer and then you get the current PHP memory limit like this:

$configuration = new \BrandEmbassy\Memory\MemoryConfiguration();
$limitProvider = new \BrandEmbassy\Memory\MemoryLimitProvider($configuration);
$limitInBytes = $memoryLimitProvider->getLimitInBytes();
Ivan Kvasnica
  • 776
  • 5
  • 13