2010-05-11 13 views
7

J'écris un analyseur en PHP qui doit être capable de gérer de grandes chaînes en mémoire, c'est donc un problème assez important. (c'est-à-dire, s'il vous plaît ne pas "optimiser prématurément" flamme moi, s'il vous plaît)Quelle est l'efficacité du substrat de PHP?

Comment fonctionne la fonction substr? Est-ce qu'il fait une deuxième copie des données de chaîne en mémoire, ou fait-il référence à l'original? Devrais-je m'inquiéter d'appeler, par exemple, $str = substr($str, 1); dans une boucle?

+2

Je pense que la mission serait le tueur, pas le substr. – CaffGeek

Répondre

3

Pour compléter le commentaire du Tchad, votre code nécessiterait que les deux chaînes (le plein et le premier-moins-premier-caractère) soient en mémoire en même temps (mais pas en raison de l'assignation comme indiqué par le Tchad). Voir:

$string = str_repeat('x', 1048576); 
printf("MEM: %d\nPEAK: %d\n", memory_get_usage(), memory_get_peak_usage()); 

substr($string, 1); 
printf("MEM: %d\nPEAK: %d :-(\n", memory_get_usage(), memory_get_peak_usage()); 

$string = substr($string, 1); 
printf("MEM: %d\nPEAK: %d :-(\n", memory_get_usage(), memory_get_peak_usage()); 

Sorties quelque chose comme (valeurs de mémoire sont en octets):

MEM: 1093256 
PEAK: 1093488 
MEM: 1093280 
PEAK: 2142116 :-(
MEM: 1093276 
PEAK: 2142116 :-(
1

Oui, vous devez faire attention à toute manipulation de chaîne dans une boucle car de nouvelles copies de la chaîne seront générées à chaque itération.

+0

Je ne suis pas un gars php, alors vous pourriez simplement dire non. En Java, il crée seulement une nouvelle référence au même tableau de caractères immuable. Donc, bien qu'il crée un nouvel objet String, il ne prend pas plus de copies du tableau char sous-jacent. Il déclare simplement que les décalages sont différents. Est-ce que php crée réellement une nouvelle copie du tableau char? Ou seulement référence le même tableau char. – corsiKa

4

Si vous recherchez vraiment l'efficacité, vous devez garder un pointeur - je veux dire index - avec votre chaîne. De nombreuses fonctions de chaîne acceptent un décalage pour commencer à fonctionner (comme le troisième paramètre de strpos()). Normalement, je recommanderais d'écrire un objet pour envelopper cette fonctionnalité, mais si vous prévoyez de l'utiliser beaucoup, cela pourrait causer un goulot d'étranglement au niveau des performances. Voici un exemple de ce que je veux dire (sans OO):

while ($whatever) { 
    $pos = strpos($string, $myToken, $startIndex); 
    # do something using $pos 
    $startIndex = $pos; 
} 

Si vous voulez, vous pouvez écrire votre propre classe wrapper qui fait ces opérations de chaîne et voir si elle a un impact de vitesse:

class _String { 
    private $string; 
    private $startIndex; 
    private $length; 
    public function __construct($string) { 
     $this->string = $string; 
     $this->startIndex = 0; 
     $this->length = strlen($string); 
    } 
    public function substr($from, $length = NULL) { 
     $this->startIndex = $from; 
     if ($length !== NULL) { 
      $this->endIndex = $from + $length; 
     } 
    } 
    # other functions you might use 
    # ... 
} 
+0

Les chaînes Java normales effectuent automatiquement ces opérations. Pourquoi ne pas PHP? – Pacerier