Skip to content
Advertisement

Where to put arrays with constant value that will be accessed many times?

I have some arrays storing the possible parameters for some 3D printer commands. I use this to check if the command is legal. I am confused about where I should put these arrays. These arrays will only be accessed in the formatcheck function, and the function will be called many times as there are thousands of commands to check. Should I put these in the formatcheck function as variables or at the beginning of the class the formatcheck function is in, as private static variables?

public function checkFileGcodeFormat()
{
    $Ms = array(82, 83, 84, 104, 106, 107, 109, 140, 190);
    $Gs = array(0, 1, 20, 21, 28, 90, 91, 92);
    $Ts = array(0, 1);
    if (
      !(
        $this->hasM() 
        && $this->hasNoXYZ() 
        && in_array($this->M, $this->Ms)
      ) 
      ||
      (
        $this->hasG() 
        && in_array($this->G, $this->Gs)
      ) 
      ||
      (
        $this->hasT() 
        && $this->hasNoXYZ() 
        && in_array($this->T, $this->Ts)
      ) 
    )
        return false;
    else
        return true;
}   

or:

private static $Ms = array(82, 83, 84, 104, 106, 107, 109, 140, 190);
private static $Gs = array(0, 1, 20, 21, 28, 90, 91, 92);
private static $Ts = array(0, 1);
...
...
public function checkFileGcodeFormat()
{
    if (
      !(
        $this->hasM() 
        && $this->hasNoXYZ() 
        && in_array($this->M, $this->Ms)
      ) 
      ||
      (
        $this->hasG() 
        && in_array($this->G, $this->Gs)
      ) 
      ||
      (
        $this->hasT() 
        && $this->hasNoXYZ() 
        && in_array($this->T, $this->Ts)
      ) 
    )
        return false;
    else
        return true;
}

Advertisement

Answer

TL;DR: Use a class constant for maximum performance (see at the end of the answer).

Let’s look at the performance characteristics of the different versions (and why):

PHP 5

Arrays in static properties are created at compile time, very quickly, without involvement of the VM. Accessing static properties though is a bit slower than accessing normal variables, but still much faster than recreating the array on every run.

Arrays in normal functions get re-created at run-time with every run, in any case. And creation at run-time in VM means that every element is added one-by-one, in individual opcodes, which means quite a bit of overhead (especially if the array is larger than just 1-2 elements).

PHP 7.0

Arrays in normal functions [in general] are created a bit faster due to array creation in general being sped up (optimizations in HashTable handling). If it’s all constant values, it’s cached in the internal constant values array, but duplicated upon each access. However doing a direct highly specialized copying action is obviously faster than adding elements one-by-one to the array like in PHP 5.

Opcache is marking them as IMMUTABLE internally, which allows direct access [so you get full speed with opcache]. (See also https://blog.blackfire.io/php-7-performance-improvements-immutable-arrays.html)

PHP 7.1

Arrays are natively always cached in the internal constant values array, with copy-on-write semantics.

Now using a static property is slower as looking up a static property is less performant than a simple write to a variable. [Direct access to a variable has no extra overhead.]


Also note that since PHP 5.6 you can declare (class) constants with the value of an array. PHP 7.1 allows direct substitution of class constants of the same class and will add the array directly to the internal constant values array for direct usage with in_array.

I.e. the fastest code is (with 7.1 at least):

private const Ms = array(82, 83, 84, 104, 106, 107, 109, 140, 190);
private const Gs = array(0, 1, 20, 21, 28, 90, 91, 92);
private const Ts = array(0, 1);
...
...
public function checkFileGcodeFormat()
{
    if (! ($this->hasM() && $this->hasNoXYZ() && in_array($this->M, self::Ms)) || ($this->hasG() && in_array($this->G, self::Gs)) || ($this->hasT() && $this->hasNoXYZ() && in_array($this->T, self::Ts)) )
        return false;
    else
        return true;
}
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement