2

If I have the option of using a global variable or passing a variable, which option is better in terms of speed and memory usage?

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

$var='string';
func();


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

$var='string';
func($var);
2
  • 2
    I don't think it will make much of a difference, and readability of code is important. Even if passing variables is slightly slower (and I don't know if it is) you should still generally avoid global variables. Commented Feb 25, 2014 at 0:07
  • With such little code, I would assume that there's no measurable differenc Commented Jan 13 at 10:51

5 Answers 5

6

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

When in doubt, test! The below results show that:

  1. Passing a 1Mb string by parameter is vastly more performant than ref by global $var
  2. Passing a 1Mb string by parameter is approximately equally performant as using $GLOBALS['var']
  3. Using global $var in the below manner seems to mess with GC reference counts on the memory and is ridiculously slow. Apparently, don't use global $var for cases like this made up one.

Results (see code further below):
Time is seconds elapsed, memory is memory potentially leaked.

$ 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

Test Code:

<?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";
Sign up to request clarification or add additional context in comments.

4 Comments

I have tested your code, and for me, difference is 0.005 in most cases. Using PHP7.0. Thanks.
Indeed. These results were from 2014. See @magallanes answer above for updates using modern php versions.
@KevinVaughan Boop. .
Now they are same (year 2023, PHP 8.2). I tested the script. The three functions are all around 0.02s, memory are all 0.
3

The global variable will probably be faster, but not in a way that it's detectable unless you microbenchmark it. So base your decisions on which code is more readable/maintainable (which will be passing the variable in almost all cases), not some speed advantage you'll normally never notice.

Comments

3

Tl/dr: define const=const > parameter > global > $GLOBAL

However, the difference is really marginal, for 10 millions of operations, the difference is less than a second.

I ran the example of @Kevin Vaughan (I ran it 10'000'000 instead of 1'000'000) Windows 10 64bits, php 7.2 64bits

    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

The memory leak is gone, however, the difference of performance is really small. Yet, passing the values by parameter is still fast.

Updated code with new functions.

<?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_const2();
}
$timeEnd = microtime(true);
$memoryEnd = memory_get_usage(true);
print "GLOBALS array const\nTime: ".($timeEnd - $timeStart)."s\nMemory: ".($memoryEnd-$memoryStart)."\n\n";


echo "</pre>";

Comments

2

In PHP, global $var is essentially running $var = &$_GLOBALS['var'] behind the scenes, so you'd be looking at a search time of O(n). The cost in running the function with the variable passed in is so little that it's not worth optimizing against.

Generally, you should find a balance between what is functionally correct, what is easy to read / test, and what is fast. In this case, the speed difference is negligible, while the cost to overall readability and testability is pretty severe.

Comments

1

I don't think you would see any performance difference. But you should be aware it's not a good idea to use a global variable just for doing it. Eventually it would be a problem, for reading the code, developing and testing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.