2010-05-11 16 views
7

Ich schreibe einen Parser in PHP, der in der Lage sein muss, große In-Memory-Strings zu handhaben, also ist dies ein etwas wichtiges Problem. (dh, bitte nicht "vorzeitige Optimierung" Flamme mich, bitte)Wie effizient ist PHP's substr?

Wie funktioniert die substr Funktion? Macht es eine zweite Kopie der String-Daten im Speicher oder verweist es auf das Original? Sollte ich mir Sorgen machen, zB $str = substr($str, 1); in einer Schleife anzurufen?

+2

Ich würde denken, dass die Zuordnung der Mörder wäre, nicht die substr. – CaffGeek

Antwort

3

Um den Kommentar von Chad weiterzuführen, würde Ihr Code beide Zeichenfolgen (das vollständige Zeichen und das Zeichen mit dem vollen Ein-Minus-Zeichen) gleichzeitig im Speicher haben (allerdings nicht aufgrund der Zuweisung, wie von Chad angegeben). Siehe:

$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()); 

Ausgänge so etwas wie (Speicherwerte sind in Bytes):

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

Ja, Sie sollten vorsichtig sein, wenn Sie eine String-Manipulation innerhalb einer Schleife durchführen, da bei jeder Iteration neue Kopien der Zeichenfolge generiert werden.

+0

Ich bin kein PHP-Typ, also könnte man einfach nein sagen. In Java wird nur ein neuer Verweis auf dasselbe unveränderliche char-Array erstellt. Während also ein neues String-Objekt erstellt wird, werden nicht mehr Kopien des zugrunde liegenden char-Arrays gespeichert. Es erklärt lediglich, dass die Offsets unterschiedlich sind. Erstellt PHP tatsächlich eine neue Kopie des Char-Arrays? Oder referenziere nur das gleiche char-Array. – corsiKa

4

Wenn Sie wirklich in Effizienz suchen, müssen Sie einen Zeiger - ich meine Index - mit Ihrer Zeichenfolge. Viele String-Funktionen akzeptieren einen Offset, um von (wie strpos() dritten Parameter) zu starten. Normalerweise würde ich empfehlen, ein Objekt zu schreiben, um diese Funktionalität zu umschließen, aber wenn Sie davon ausgehen, dass Sie viel davon verwenden, könnte dies zu einem Performance-Engpass führen. Hier ist ein Beispiel dafür, was ich meine (ohne OO):

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

Wenn Sie möchten, können Sie Ihre eigene Wrapper-Klasse schreiben, die diese String-Operationen tun und sehen, ob es eine Geschwindigkeit auswirkt:

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

Normale Java-Strings erledigen diese Dinge automatisch. Warum nicht PHP? – Pacerier