2010-05-11 8 views
7

Estoy escribiendo un programa de análisis en PHP que debe ser capaz de manejar grandes cadenas en memoria, por lo que este es un tema algo importante. (Es decir, por favor, no "optimizar prematura" me llama, por favor)¿Qué tan eficiente es el substr de PHP?

¿Cómo funciona el substr función? ¿Hace una segunda copia de los datos de cadena en la memoria, o hace referencia al original? ¿Debería preocuparme por llamar, por ejemplo, al $str = substr($str, 1); en un bucle?

+2

Me gustaría pensar que la asignación sería el asesino, no el substr. – CaffGeek

Respuesta

3

para más comentarios de Chad, su código requeriría ambas cadenas (el lleno y el completo menos de uno de primer carácter) para estar en la memoria al mismo tiempo (aunque no debido a la asignación como declaró Chad). Ver:

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

algo así como salidas (valores de la memoria son en bytes):

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

Sí, usted debe tener cuidado de hacer cualquier manipulación de cadenas dentro de un bucle que se generarán nuevas copias de la cadena en cada iteración.

+0

No soy un tipo php, por lo que podría decir simplemente no. En Java, solo crea una nueva referencia a la misma matriz de caracteres inmutables. Por lo tanto, aunque crea un nuevo objeto String, no necesita almacenar más copias de la matriz char subyacente. Simplemente declara que las compensaciones son diferentes. ¿PHP realmente crea una nueva copia de la matriz de caracteres? O solo hace referencia a la misma matriz de caracteres. – corsiKa

4

Si realmente está buscando la eficiencia, necesitará mantener un puntero - es decir, índice - con su cadena. Muchas funciones de cadena aceptan un desplazamiento para comenzar a operar (como el tercer parámetro de strpos()). Normalmente, recomendaría escribir un objeto para ajustar esta funcionalidad, pero si espera usar mucho eso, podría causar un cuello de botella de rendimiento. He aquí un ejemplo de lo que quiero decir (sin OO):

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

Si lo desea, puede escribir su propia clase de contenedor que hace estas operaciones de cadena y ver si tiene un impacto velocidad:

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

Las cadenas normales de Java hacen estas cosas automáticamente. ¿Por qué PHP no? – Pacerier