PHP中的全局变量或传递变量? (性能)

时间:2014-02-25 00:03:33

标签: php

如果我可以选择使用全局变量或传递变量,哪个选项在速度和内存使用方面更好?

// global variable
function func(){
  global $var;
  echo $var;
}

$var='string';
func();


// passing variable
function func($var){
  echo $var;
}

$var='string';
func($var);

5 个答案:

答案 0 :(得分:4)

TLDR: Pass by parameter = $GLOBALS element>>> global $var

如有疑问,请测试!以下结果表明:

  1. 通过参数传递1Mb字符串比全局$ var
  2. 更高效
  3. 按参数传递1Mb字符串与使用$ GLOBALS ['var']
  4. 的效果大致相同
  5. 以下面的方式使用全局$ var似乎弄乱了内存上的GC引用计数,而且速度非常慢。显然,不要在这样的情况下使用全局$ var。
  6. 结果(请参阅下面的代码):
    时间是经过几秒钟,内存可能是内存泄漏。

    $ php -e test.php
    Pass value by parameter
    Time: 0.20166087150574s
    Memory: 0
    
    Global var reference
    Time: 70.613216876984s
    Memory: 1048576
    
    GLOBALS array reference
    Time: 0.22573900222778s
    Memory: 0
    

    测试代码:

    <?php
    
    $baseVar = str_repeat('x', 1000000);
    $GLOBALS['myVar'] = $baseVar;
    
    function testfunc_param($paramVar) {
        $localVar = $paramVar;
        return $localVar;
    }
    
    function testfunc_global() {
        global $myVar;
        $localVar = $myVar;
        return $localVar;
    }
    
    function testfunc_globalsarray() {
        $localVar = $GLOBALS['myVar'];
        return $localVar;
    }
    
    
    // Testing passing value by parameter
    memory_get_usage(); // in case this procs garbage collection
    $memoryStart = memory_get_usage(true);
    $timeStart = microtime(true);
    for ($i = 0; $i < 1000000; $i++) {
        testfunc_param($baseVar);
    }
    $timeEnd = microtime(true);
    $memoryEnd = memory_get_usage(true);
    print "Pass value by parameter\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";
    
    
    // Testing reference to global variable
    memory_get_usage(); // in case this procs garbage collection
    $memoryStart = memory_get_usage(true);
    $timeStart = microtime(true);
    for ($i = 0; $i < 1000000; $i++) {
        testfunc_global();
    }
    $timeEnd = microtime(true);
    $memoryEnd = memory_get_usage(true);
    print "Global var reference\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";
    
    
    // Testing reference to global variable via $GLOBALS
    memory_get_usage(); // in case this procs garbage collection
    $memoryStart = memory_get_usage(true);
    $timeStart = microtime(true);
    for ($i = 0; $i < 1000000; $i++) {
        testfunc_globalsarray();
    }
    $timeEnd = microtime(true);
    $memoryEnd = memory_get_usage(true);
    print "GLOBALS array reference\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";
    

答案 1 :(得分:3)

全局变量可能会更快,但除非你对它进行微基准测试,否则它不会被检测到。因此,决定哪些代码更易读/可维护(几乎在所有情况下都会传递变量),而不是通常从未注意到的速度优势。

答案 2 :(得分:1)

我认为你不会看到任何性能差异。但是你应该意识到使用全局变量并不是一个好主意。最终,阅读代码,开发和测试将是一个问题。

答案 3 :(得分:1)

在PHP中,global $var基本上在幕后运行$var = &$_GLOBALS['var'],因此您需要查看O(n)的搜索时间。使用传入的变量运行函数的成本非常低,以至于不值得优化。

通常,您应该在功能正确,易于阅读/测试和快速之间找到平衡点。在这种情况下,速度差异可以忽略不计,而整体可读性和可测试性的成本非常高。

答案 4 :(得分:0)

  

Tl / dr:定义const = const>参数>全局> $ GLOBAL

     

但是,差异确实很小,对于1000万次操作,差异不到一秒钟。

我运行了@Kevin Vaughan的示例(我运行了10'000'000而不是1'000'000)Windows 10 64位,php 7.2 64位

    Pass value by parameter
Time: 0.62202191352844s
Memory: 0

Global var reference
Time: 0.70083403587341s
Memory: 0

GLOBALS array reference
Time: 0.84828305244446s
Memory: 0

GLOBALS array reference2
Time: 0.80545091629028s
Memory: 0

GLOBALS array const define
Time: 0.57029700279236s
Memory: 0

GLOBALS array const
Time: 0.57260584831238s
Memory: 0

内存泄漏消失了,但是,性能差异确实很小。但是,通过参数传递值仍然很快。

具有新功能的更新代码。

<?php
echo "<pre>";
$baseVar = str_repeat('x', 1000000);
$GLOBALS['myVar'] = $baseVar;
define('BASEVAR',$baseVar);

const BASEVAR2=BASEVAR;

function testfunc_param($paramVar) {
    $localVar = $paramVar;
    return $localVar;
}

function testfunc_global() {
    global $myVar;
    $localVar = $myVar;
    return $localVar;
}

function testfunc_globalsarray() {
    $localVar = $GLOBALS['myVar'];
    return $localVar;
}

function testfunc_globalsarray2() {
    return $GLOBALS['myVar'];
}

function testfunc_const() {
    return BASEVAR;
}

function testfunc_const2() {
    return BASEVAR2;
}

// Testing passing value by parameter
memory_get_usage(); // in case this procs garbage collection
$memoryStart = memory_get_usage(true);
$timeStart = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    testfunc_param($baseVar);
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "Pass value by parameter\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";


// Testing reference to global variable
memory_get_usage(); // in case this procs garbage collection
$memoryStart = memory_get_usage(true);
$timeStart = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    testfunc_global();
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "Global var reference\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";


// Testing reference to global variable via $GLOBALS
memory_get_usage(); // in case this procs garbage collection
$memoryStart = memory_get_usage(true);
$timeStart = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    testfunc_globalsarray();
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "GLOBALS array reference\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";

// Testing reference to global variable via $GLOBALS
memory_get_usage(); // in case this procs garbage collection
$memoryStart = memory_get_usage(true);
$timeStart = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    testfunc_globalsarray2();
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "GLOBALS array reference2\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";

// Testing reference to global variable via $GLOBALS
memory_get_usage(); // in case this procs garbage collection
$memoryStart = memory_get_usage(true);
$timeStart = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    testfunc_const();
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "GLOBALS array const define\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";

// Testing reference to global variable via $GLOBALS
memory_get_usage(); // in case this procs garbage collection
$memoryStart = memory_get_usage(true);
$timeStart = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    testfunc_const();
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "GLOBALS array const\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";


echo "</pre>";