34 votes

Où placer des tableaux à valeur constante auxquels on accédera plusieurs fois?

J'ai quelques tableaux de stocker les paramètres possibles pour la 3D aux commandes de l'imprimante. Je l'utilise pour vérifier si la commande est légal. Je suis confus sur où je devrais mettre ces tableaux. Ces tableaux ne seront accessibles que dans le formatcheck de la fonction, et la fonction sera appelée autant de fois qu'il y a des milliers de commandes pour vérifier. Dois-je placer ces éléments dans le formatcheck fonction de variables ou au début de la classe la formatcheck de la fonction, alors que les variables statiques?

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, $Ms)) || ($this->hasG() && in_array($this->G, $Gs)) || ($this->hasT() && $this->hasNoXYZ() && in_array($this->T, $Ts)) )
        return false;
    else
        return true;
}   

ou:

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, 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;
}

33voto

bwoebi Points 12576

TL;DR: l'Utilisation d'une constante de classe pour un maximum de performance (voir à la fin de la réponse).

Regardons les caractéristiques de performance des différentes versions (et pourquoi):

PHP 5

Les tableaux dans les propriétés statiques sont créés au moment de la compilation, très rapidement, sans la participation de la VM. Accéder aux propriétés statiques mais est un peu plus lent que l'accès à la normale des variables, mais toujours beaucoup plus rapide que de les recréer le tableau sur chaque course.

Les tableaux dans les fonctions normales de re-créé au moment de l'exécution de chaque course, en tout cas. Et de la création au moment de l'exécution de la VM signifie que chaque élément est ajouté, un par un, dans les différents opérateurs, ce qui signifie que tout à fait un peu de surcharge (surtout si le tableau est plus grand que juste 1-2 éléments).

PHP 7.0

Les tableaux dans les fonctions normales [en général] sont créés un peu plus rapide en raison de la création de la matrice, en général, être accéléré (optimisations dans la table de hachage de manutention). Si c'est une constante des valeurs, il est mis en cache à l'intérieur des valeurs de constantes tableau, mais dupliqué sur chaque accès. Cependant directement hautement spécialisé de la copie d'action est évidemment plus rapide que l'ajout d'éléments un par un à la matrice comme dans PHP 5.

Opcache est en les marquant comme IMMUABLE en interne, qui permet un accès direct [de sorte que vous obtenez la pleine vitesse avec opcache]. (Voir aussi https://blog.blackfire.io/php-7-performance-improvements-immutable-arrays.html)

PHP 7.1

Les tableaux sont nativement toujours mis en cache à l'intérieur des valeurs de constantes tableau, avec copie à l'écriture de la sémantique.

Maintenant, en utilisant une propriété statique est plus lente que la recherche d'une propriété statique est moins performant qu'une simple écriture d'une variable. [Accès Direct à une variable n'a pas de frais généraux supplémentaires.]


Notez également que depuis PHP 5.6, vous pouvez déclarer (classe) les constantes de la valeur d'un tableau. PHP 7.1 permet de remplacement direct des constantes de classe de la même classe et ajouter le tableau directement à l'intérieur des valeurs de constantes de matrice pour une utilisation directe avec in_array.

I. e. le code est plus rapide (7.1):au moins

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;
}

10voto

sevavietl Points 2971

Je pense que la définition de tableau à une propriété est en fait plus de sens, comme les groupes définis à l'intérieur de l'méthodes sont créés à chaque appel.

Mais je veux faire un autre point. Si vous avez plutôt des grands tableaux de chercher la valeur dans l', il est plus important de leur structure. Je dirais ceci:

array(
    82 => true,
    83 => true,
    84 => true,
    104 => true,
    106 => true,
    107 => true,
    109 => true,
    140 => true,
    190 => true
);

array(
    0 => true,
    1 => true,
    20 => true,
    21 => true,
    28 => true,
    90 => true,
    91 => true,
    92 => true
);

array(
    0 => true,
    1 => true
);

Ayant cette structure, vous pouvez utiliser isset (O(1)) au lieu de in_array (O(n)).

Voici quelques autres questions concernant l' isset vs in_array:

Et voici quelques messages avec des points de repère:

Le dernier est un peu vieux, mais je pense que le ratio de la réserve.

Donc, pour résumer. Lorsque vous utilisez isset du temps de recherche est constante (en fait, il peut varier, mais il peut être ignoré). Lorsque vous utilisez in_array du temps de recherche dépend de la position de l'élément (et donc sur la taille de la matrice). Même sur des petites baies isset fonctionne plus rapidement.

6voto

smcjones Points 1410

Une phrase à emporter: les constantes de Classe peut être plus rapide, mais la mémoire ne sera probablement pas d'importance, et à l'aide de l' Injection de Dépendance Modèle de Conception sera plus efficace en terme de mémoire et flexible.

Tandis qu'une constante de classe ou propriété statique sera plus rapide que de créer un tableau dans une fonction (voir bwoebi réponse) parce qu'il est intégré dans la mémoire une fois et peut être consulté à plusieurs reprises, il n'est en aucune façon la méthode la plus efficace disponible, ou la méthode recommandée pour résoudre le problème à la racine de l'OP cherche à résoudre.

Si vous êtes certain qu'aucune donnée n'est jamais va changer dans l'avenir, ou vous n'êtes jamais allez vouloir utiliser des jeux de données différents à des moments différents, même pour les tests, vous pouvez être en mesure de s'en tirer avec cette méthode, de toute façon. Si vous voulez plus flexible de code, les constantes de classe ou de propriétés statiques peuvent causer de sérieux problèmes. Comme je l'expliquerai plus tard, la quantité de mémoire utilisée ou enregistrée est peu probable que la matière. De plus en plus important à prendre en compte:

  • Comment facile est-ce que ça va être de modifier mon code dans l'avenir?
  • La flexibilité est mon code à l'évolution des circonstances
  • Comment est-il facile de l'unité de tester mon code?

Avant de s'engager à la plus efficace en terme de mémoire route, assurez-vous d'équilibrer d'autres formes de l'efficience, de l'efficacité de votre temps dans le développement et le débogage.

Pourquoi la Mémoire ne peut pas d'importance

En raison de la vitesse des ordinateurs modernes, les performances frappé vous de l'expérience entre les deux versions devraient rarement faire une différence. Disk I/O est plus souvent un problème de mémoire. Si votre serveur fonctionne sur une TRÈS petite quantité de mémoire et vous vous attendez à volume très élevé, alors la mémoire de l'efficacité de votre code sera plus important que si vous avez de volume modéré et modérée de la mémoire.

Pour mettre les choses en perspective, voir cet article sur l'efficacité de tableaux en PHP. La vente à emporter? Même si PHP5 tableaux sont horriblement inefficace, même un tableau de 100 000 entiers prendra environ 14M. C'est BEAUCOUP, mais étant donné que la moyenne script PHP a une limite de mémoire de 128MO, et le minimum de recommandations pour le serveur d'appel d'environ 2 GO de mémoire, ce semble soudain différent.

Cela signifie que vous devriez vous inquiéter à ce sujet si le reste de votre code est inefficace, ou vous avez un volume élevé, comparativement à une insuffisance de mémoire. Qui sera la cause de votre demande de ralentir et/ou de votre système à planter.

Peu importe, dans une situation où vous êtes à explorer les choix architecturaux depuis le début, je vous recommande fortement d'un modèle de conception. À savoir, l' Injection de Dépendance modèle de conception. C'est pour un certain nombre de raisons, y compris le code de la flexibilité et de tests unitaires, mais aussi chaleureuse empreinte mémoire. De ce fait, il serait probablement être considérées comme des bonnes pratiques sur l'une de ces deux options vous sont recommander.

Pourquoi ne pas statique de propriétés

Au départ, l'itinéraire le plus simple est d'utiliser les propriétés statiques. Cependant, dans mon expérience, la route la plus facile n'est pas toujours le meilleur itinéraire, et peut souvent être le plus difficile à maintenir. Un problème, c'est que vos fonctions/méthodes seront probablement appel d'une autre classe à l'intérieur. Comme exemple, nous allons créer deux classes: MyFooClass et DoStuff, et de voir comment ils peuvent interagir par défaut.

class MyFooClass
{
    public static $Ms = array(82, 83, 84, 104, 106, 107, 109, 140, 190);
    public static $Gs = array(0, 1, 20, 21, 28, 90, 91, 92);
    public static $Ts = array(0, 1);
}

class DoStuff
{
    public function oneOfThousands()
    {
        $array = MyFooClass::$Gs;
        //... do stuff
    }
}

Maintenant, si jamais vous voulez insérer différentes valeurs de tableau à des fins différentes, ou si vous voulez de l'unité de test avec moins ou plus de paramètres, les complications abondent.

L'Injection de dépendance à la Rescousse!

Comme tous les modèles de conception de l'Injection de Dépendance résout un problème. Dans ce cas, le problème est facilement et efficacement la transmission de valeurs entre plusieurs fonctions/méthodes, sans sacrifier la flexibilité. À l'aide d'une base DI motif, vous pouvez obtenir vos tableaux initialisés dans la non-propriétés statiques et passer un seul objet contenant cette propriété de tableau pour chaque partie de votre code. Qui vous permettra d'éliminer vos inquiétudes à propos de la performance.

Exemple:

class MyFooClass
{
    private $Ms, $Gs, $Ts;

    public function __construct()
    {
        $this->Ms = array(82, 83, 84, 104, 106, 107, 109, 140, 190);
        $this->Gs = array(0, 1, 20, 21, 28, 90, 91, 92);
        $this->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;
    }
}


// DI here:
$foo = new MyFooClass();

$bar = new MyBarClass();
$bar->setArrays($foo);

//alternative DI approach - parameters in constructor
$bar = new MyBarClass($foo);

Dans votre MyBarClass, de l'affectation d'un MyFooClass objet à une propriété $foo. Vous pouvez ensuite appeler une méthode publique ou d'une propriété de cet objet en $this->foo. Par exemple: $this->foo->checkFileGcodeFormat().

Avec ce modèle de conception:

  • Lorsque vous souhaitez développer une nouvelle unité de test, il sera beaucoup plus facile de le faire.
  • Si jamais vous voulez/besoin de mettre en œuvre un sous-ensemble de Gcodes pour une application, il suffit de passer un objet différent avec différentes valeurs de tableau.
  • De même, si vous voulez tester un nouveau Traitement sur une nouvelle classe sans la présenter à chaque partie de votre script, vous pouvez.
  • La mémoire consacré est de la taille d'un pointeur en PHP (qui est la même que la taille d'un pointeur en C... 8 octets dans une architecture en 64 bit).

Conclusion

  • Si vous le pouvez, je vous conseille d'utiliser l'Injection de Dépendance Modèle de Conception.
  • Vous pouvez choisir une propriété statique pour une meilleure empreinte mémoire (note: Ce n'est pas mutuellement exclusif de l'Injection de Dépendance, mais il est moins important si vous utiliser l'Injection de Dépendance).
  • Dans un standard de configuration du serveur web, avec un trafic modéré, il est peu probable que votre consommation de mémoire n'aura d'importance, si vous utilisez des propriétés statiques ou appelez un tableau à partir de l'intérieur d'une fonction.

5voto

Robbie Points 9099

Si ils ne changent JAMAIS, alors vous devriez être mise en forme que const. Il est cuit au four au moment de la compilation, et donc sera le plus rapide.

const MS = [82, 83, 84, 104, 106, 107, 109, 140, 190];
const GS = [0, 1, 20, 21, 28, 90, 91, 92];
const TS = [0, 1];

if (!in_array($this->M, MS)) {
    ...
}

ou

class () {
    const MS = [82, 83, 84, 104, 106, 107, 109, 140, 190];
    const GS = [0, 1, 20, 21, 28, 90, 91, 92];
    const TS = [0, 1];

    if (!in_array($this->M, self::MS)) {
        ...
    }
}

Quelques remarques:

  • const sont comme define mais cuit au four au moment de la compilation, légèrement plus rapide que le définit et variables tableaux.
  • vous pouvez définir const au niveau mondial ou au niveau de la classe (http://php.net/manual/en/language.oop5.constants.php). Qu'à partir de php 7.1 vous pouvez également déclarer la classe consts privés/public/protected etc.
  • J'ai utilisé des lettres majuscules pour les définit ce qui est officieux de la norme, mais pas une exigence.

4voto

rock3t Points 1309

Si vous êtes vraiment à la recherche sur la compréhension de la façon dont le code de la performance peut être mesurée, vous devriez vous familiariser avec Big-O de notation.

Qu'est-ce que Big-O? Big-O feuille de triche

Autre que cela, les définir comme classe protégée propriétés de base de données statiques.

class foo
{
    protected static $bar = array();
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X