WordPress.org

Make WordPress Core

Changeset 38015


Ignore:
Timestamp:
07/08/2016 02:36:37 PM (4 years ago)
Author:
ocean90
Message:

Bootstrap: Enhance core's memory limit handling.

  • Don't lower memory limit if the current limit is greater than WP_MAX_MEMORY_LIMIT.
  • Set WP_MEMORY_LIMIT and WP_MAX_MEMORY_LIMIT to current limit if the memory_limit setting can't be changed at runtime.
  • Use wp_convert_hr_to_bytes() when parsing the value of the memory_limit setting because it can be a shorthand or an integer value.
  • Introduce wp_raise_memory_limit( $context ) to raise the PHP memory limit for memory intensive processes. This DRYs up some logic and includes the existing admin_memory_limit and image_memory_limit filters. The function can also be used for custom contexts, the {$context}_memory_limit filter allows to customize the limit.
  • Introduce wp_is_ini_value_changeable( $setting ) to determine whether a PHP ini value is changeable at runtime.
  • Remove a function_exists( 'memory_get_usage' ) check. Since PHP 5.2.1 support for memory limit is always enabled.

Related commits: [38011-38013]

Props jrf, A5hleyRich, swissspidy, ocean90.
Fixes #32075.

Location:
trunk
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/admin.php

    r37998 r38015  
    139139
    140140if ( current_user_can( 'manage_options' ) ) {
    141     /**
    142      * Filters the maximum memory limit available for administration screens.
    143      *
    144      * This only applies to administrators, who may require more memory for tasks like updates.
    145      * Memory limits when processing images (uploaded or edited by users of any role) are
    146      * handled separately.
    147      *
    148      * The WP_MAX_MEMORY_LIMIT constant specifically defines the maximum memory limit available
    149      * when in the administration back end. The default is 256M, or 256 megabytes of memory.
    150      *
    151      * @since 3.0.0
    152      *
    153      * @param string 'WP_MAX_MEMORY_LIMIT' The maximum WordPress memory limit. Default 256M.
    154      */
    155     @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
     141    wp_raise_memory_limit( 'admin' );
    156142}
    157143
  • trunk/src/wp-admin/includes/file.php

    r37598 r38015  
    570570        return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
    571571
    572     // Unzip can use a lot of memory, but not this much hopefully
    573     /** This filter is documented in wp-admin/admin.php */
    574     @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
     572    // Unzip can use a lot of memory, but not this much hopefully.
     573    wp_raise_memory_limit( 'admin' );
    575574
    576575    $needed_dirs = array();
  • trunk/src/wp-admin/includes/image-edit.php

    r37985 r38015  
    586586    $post = get_post( $post_id );
    587587
    588     /** This filter is documented in wp-admin/admin.php */
    589     @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
     588    wp_raise_memory_limit( 'admin' );
    590589
    591590    $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
  • trunk/src/wp-includes/class-wp-image-editor-gd.php

    r37592 r38015  
    9797            return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
    9898
    99         /**
    100          * Filters the memory limit allocated for image manipulation.
    101          *
    102          * @since 3.5.0
    103          *
    104          * @param int|string $limit Maximum memory limit to allocate for images. Default WP_MAX_MEMORY_LIMIT.
    105          *                          Accepts an integer (bytes), or a shorthand string notation, such as '256M'.
    106          */
    107         $image_memory_limit = apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT );
    108 
    10999        // Set artificially high because GD uses uncompressed images in memory.
    110         @ini_set( 'memory_limit', $image_memory_limit );
     100        wp_raise_memory_limit( 'image' );
    111101
    112102        $this->image = @imagecreatefromstring( file_get_contents( $this->file ) );
  • trunk/src/wp-includes/class-wp-image-editor-imagick.php

    r37592 r38015  
    138138            return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file );
    139139
    140         /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */
    141         $image_memory_limit = apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT );
    142 
    143140        /*
    144141         * Even though Imagick uses less PHP memory than GD, set higher limit
    145142         * for users that have low PHP.ini limits.
    146143         */
    147         @ini_set( 'memory_limit', $image_memory_limit );
     144        wp_raise_memory_limit( 'image' );
    148145
    149146        try {
  • trunk/src/wp-includes/default-constants.php

    r38011 r38015  
    2929    /**#@-*/
    3030
    31     // set memory limits
    32     if ( !defined('WP_MEMORY_LIMIT') ) {
    33         if ( is_multisite() ) {
    34             define('WP_MEMORY_LIMIT', '64M');
     31    $current_limit     = @ini_get( 'memory_limit' );
     32    $current_limit_int = wp_convert_hr_to_bytes( $current_limit );
     33
     34    // Define memory limits.
     35    if ( ! defined( 'WP_MEMORY_LIMIT' ) ) {
     36        if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
     37            define( 'WP_MEMORY_LIMIT', $current_limit );
     38        } elseif ( is_multisite() ) {
     39            define( 'WP_MEMORY_LIMIT', '64M' );
    3540        } else {
    36             define('WP_MEMORY_LIMIT', '40M');
     41            define( 'WP_MEMORY_LIMIT', '40M' );
    3742        }
    3843    }
    3944
    4045    if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) ) {
    41         define( 'WP_MAX_MEMORY_LIMIT', '256M' );
     46        if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
     47            define( 'WP_MAX_MEMORY_LIMIT', $current_limit );
     48        } elseif ( -1 === $current_limit_int || $current_limit_int > 268435456 /* = 256M */ ) {
     49            define( 'WP_MAX_MEMORY_LIMIT', $current_limit );
     50        } else {
     51            define( 'WP_MAX_MEMORY_LIMIT', '256M' );
     52        }
     53    }
     54
     55    // Set memory limits.
     56    $wp_limit_int = wp_convert_hr_to_bytes( WP_MEMORY_LIMIT );
     57    if ( -1 !== $current_limit_int && ( -1 === $wp_limit_int || $wp_limit_int > $current_limit_int ) ) {
     58        @ini_set( 'memory_limit', WP_MEMORY_LIMIT );
    4259    }
    4360
    4461    if ( ! isset($blog_id) )
    4562        $blog_id = 1;
    46 
    47     // set memory limits.
    48     if ( function_exists( 'memory_get_usage' ) ) {
    49         $current_limit = @ini_get( 'memory_limit' );
    50         $current_limit_int = intval( $current_limit );
    51         if ( false !== strpos( $current_limit, 'G' ) )
    52             $current_limit_int *= 1024;
    53         $wp_limit_int = intval( WP_MEMORY_LIMIT );
    54         if ( false !== strpos( WP_MEMORY_LIMIT, 'G' ) )
    55             $wp_limit_int *= 1024;
    56 
    57         if ( -1 != $current_limit && ( -1 == WP_MEMORY_LIMIT || $current_limit_int < $wp_limit_int ) )
    58             @ini_set( 'memory_limit', WP_MEMORY_LIMIT );
    59     }
    6063
    6164    if ( !defined('WP_CONTENT_DIR') )
  • trunk/src/wp-includes/deprecated.php

    r37985 r38015  
    31763176        return __('The GD image library is not installed.');
    31773177
    3178     /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */
    3179     $image_memory_limit = apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT );
    3180 
    31813178    // Set artificially high because GD uses uncompressed images in memory.
    3182     @ini_set( 'memory_limit', $image_memory_limit );
     3179    wp_raise_memory_limit( 'image' );
    31833180
    31843181    $image = imagecreatefromstring( file_get_contents( $file ) );
  • trunk/src/wp-includes/functions.php

    r37991 r38015  
    53805380    return false;
    53815381}
     5382
     5383/**
     5384 * Attempts to raise the PHP memory limit for memory intensive processes.
     5385 *
     5386 * Only allows raising the existing limit and prevents lowering it.
     5387 *
     5388 * @since 4.6.0
     5389 *
     5390 * @param string $context  Context in which the function is called.
     5391 *                         Either 'admin', 'image' or an arbitrary other context.
     5392 *                         Defaults to 'admin'.
     5393 *                         If an arbitrary context is passed, the similarly arbitrary
     5394 *                         "{$context}_memory_limit" filter will be invoked.
     5395 * @return bool|int|string The limit that was set or false on failure.
     5396 */
     5397function wp_raise_memory_limit( $context = 'admin' ) {
     5398    // Exit early if the limit cannot be changed.
     5399    if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
     5400        return false;
     5401    }
     5402
     5403    $current_limit     = @ini_get( 'memory_limit' );
     5404    $current_limit_int = wp_convert_hr_to_bytes( $current_limit );
     5405
     5406    if ( -1 === $current_limit_int ) {
     5407        return false;
     5408    }
     5409
     5410    $wp_max_limit     = WP_MAX_MEMORY_LIMIT;
     5411    $wp_max_limit_int = wp_convert_hr_to_bytes( $wp_max_limit );
     5412    $filtered_limit   = $wp_max_limit;
     5413
     5414    switch ( $context ) {
     5415        case 'admin':
     5416            /**
     5417             * Filters the maximum memory limit available for administration screens.
     5418             *
     5419             * This only applies to administrators, who may require more memory for tasks like updates.
     5420             * Memory limits when processing images (uploaded or edited by users of any role) are
     5421             * handled separately.
     5422             *
     5423             * The WP_MAX_MEMORY_LIMIT constant specifically defines the maximum memory limit available
     5424             * when in the administration back end. The default is 256M (256 megabytes
     5425             * of memory) or the original `memory_limit` php.ini value if this is higher.
     5426             *
     5427             * @since 3.0.0
     5428             * @since 4.6.0 The default takes the original `memory_limit` into account.
     5429             *
     5430             * @param int|string $filtered_limit The maximum WordPress memory limit.
     5431             *                                   Accepts an integer (bytes), or a shorthand string
     5432             *                                   notation, such as '256M'.
     5433             */
     5434            $filtered_limit = apply_filters( 'admin_memory_limit', $filtered_limit );
     5435            break;
     5436
     5437        case 'image':
     5438            /**
     5439             * Filters the memory limit allocated for image manipulation.
     5440             *
     5441             * @since 3.5.0
     5442             * @since 4.6.0 The default takes the original `memory_limit` into account.
     5443             *
     5444             * @param int|string $filtered_limit Maximum memory limit to allocate for images.
     5445             *                                   Default WP_MAX_MEMORY_LIMIT or the original
     5446             *                                   php.ini memory_limit, whichever is higher.
     5447             *                                   Accepts an integer (bytes), or a shorthand string
     5448             *                                   notation, such as '256M'.
     5449             */
     5450            $filtered_limit = apply_filters( 'image_memory_limit', $filtered_limit );
     5451            break;
     5452
     5453        default:
     5454            /**
     5455             * Filters the memory limit allocated for arbitrary contexts.
     5456             *
     5457             * The dynamic portion of the hook name, `$context`, refers to an arbitrary
     5458             * context passed on calling the function. This allows for plugins to define
     5459             * their own contexts for raising the memory limit.
     5460             *
     5461             * @since 4.6.0
     5462             *
     5463             * @param int|string $filtered_limit Maximum memory limit to allocate for images.
     5464             *                                   Default 256M or the original php.ini memory_limit,
     5465             *                                   whichever is higher.
     5466             *                                   Accepts an integer (bytes), or a shorthand string
     5467             *                                   notation, such as '256M'.
     5468             */
     5469            $filtered_limit = apply_filters( "{$context}_memory_limit", $filtered_limit );
     5470            break;
     5471    }
     5472
     5473    $filtered_limit_int = wp_convert_hr_to_bytes( $filtered_limit );
     5474
     5475    if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) {
     5476        if ( false !== @ini_set( 'memory_limit', $filtered_limit ) ) {
     5477            return $filtered_limit;
     5478        } else {
     5479            return false;
     5480        }
     5481    } elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) {
     5482        if ( false !== @ini_set( 'memory_limit', $wp_max_limit ) ) {
     5483            return $wp_max_limit;
     5484        } else {
     5485            return false;
     5486        }
     5487    }
     5488
     5489    return false;
     5490}
  • trunk/src/wp-includes/load.php

    r38013 r38015  
    10031003    return min( $bytes, PHP_INT_MAX );
    10041004}
     1005
     1006/**
     1007 * Determines whether a PHP ini value is changeable at runtime.
     1008 *
     1009 * @since 4.6.0
     1010 *
     1011 * @link http://php.net/manual/en/function.ini-get-all.php
     1012 *
     1013 * @param string $setting The name of the ini setting to check.
     1014 * @return bool True if the value is changeable at runtime. False otherwise.
     1015 */
     1016function wp_is_ini_value_changeable( $setting ) {
     1017    static $ini_all;
     1018
     1019    if ( ! isset( $ini_all ) ) {
     1020        $ini_all = ini_get_all();
     1021    }
     1022
     1023    if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === $ini_all[ $setting ]['access'] || INI_USER === $ini_all[ $setting ]['access'] ) ) {
     1024        return true;
     1025    }
     1026
     1027    return false;
     1028}
  • trunk/tests/phpunit/tests/functions.php

    r37962 r38015  
    479479                true,
    480480            ),
    481             // Android 2.2, Android Webkit Browser 
     481            // Android 2.2, Android Webkit Browser
    482482            array(
    483483                'Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4',
    484484                true,
    485485            ),
    486             // BlackBerry 9900, BlackBerry browser 
     486            // BlackBerry 9900, BlackBerry browser
    487487            array(
    488488                'Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+',
     
    866866        $this->assertNull( wp_ext2type( 'unknown_format' ) );
    867867    }
     868
     869    /**
     870     * Tests raising the memory limit.
     871     *
     872     * Unfortunately as the default for 'WP_MAX_MEMORY_LIMIT' in the
     873     * test suite is -1, we can not test the memory limit negotiations.
     874     *
     875     * @ticket 32075
     876     */
     877    function test_wp_raise_memory_limit() {
     878        ini_set( 'memory_limit', '40M' );
     879        $this->assertSame( -1, wp_raise_memory_limit() );
     880        $this->assertEquals( '-1', ini_get( 'memory_limit' ) );
     881    }
    868882}
Note: See TracChangeset for help on using the changeset viewer.