2010-09-03 9 views
9

estaba leyendo esta página - http://deaduseful.com/blog/posts/50-php-optimisation-tips-revisitedPHP - ¿Quieres decir evitar los métodos mágicos?

Y una de las recomendaciones era evitar el uso de Métodos mágicos, citó de un PDF Rendimiento Zend que da ninguna razón para que su recomendación para evitarlos.

Después de algunas búsquedas en Google (y terminando aquí con una pregunta no relacionada) me pregunté si alguien tenía alguna recomendación en ese frente.

Uso __get() mucho en mi código, generalmente para guardar variables que no siempre uso, p.

que puede tener una tabla con el nombre, la descripción, category_id, time_added

Mi get sería algo como esto:

 
public function __get($name) { 
    switch($name) { 
     case 'name': 
     case 'desc': 
     case 'category': 
     case 'time_added': 
      $result = do_mysql_query(); 
      $this->name = $result['name']; 
      $this->desc = $result['desc']; 
      $this->category = $result['category']; 
      $this->time_added = $result['time_added']; 
      return $this->{$name}; 
     break; 
     default: 
      throw Exception("Attempted to access non existant or private property - ".$name); 
    } 
} 

Esto parece una gran manera de hacer las cosas, ya que sólo alguna vez algo de la base de datos si es necesario y puedo ver cosas como $ article-> time_added en lugar de jugar con matrices.

¿Esto se consideraría una mala práctica y una carga adicional en el servidor?

A menudo ampliaré las clases con métodos mágicos y haré algo como esto si la clase hija no coincide con algo en un get.

 
public function __get($name) { 
    switch($name) { 
     case 'name': 
     case 'desc': 
     case 'category': 
     case 'time_added': 
      $result = do_mysql_query(); 
      $this->name = $result['name']; 
      $this->desc = $result['desc']; 
      $this->category = $result['category']; 
      $this->time_added = $result['time_added']; 
      return $this->{$name}; 
     break; 
     default: 
      return parent::__get($name); 
    } 
} 

¿Sería esto una mala práctica y perjudicial para el rendimiento? La cantidad máxima de niveles que tengo cuando extiendo métodos mágicos es tres.

+0

posible duplicado de [__get/__/__ set preguntas de desempeño llamada con PHP] (http://stackoverflow.com/questions/3330852/get- set-call-performance-questions-with-php) – Gordon

Respuesta

15

Es cierto, son más lentos ... pero la diferencia es tan pequeña que la velocidad contra el código es un factor. ¿Vale la pena preocuparse por la diferencia para un desarrollo y mantenimiento más rápidos?

Ver magic benchmarks para las estadísticas

+17

+1: No puede sobrevalorar ese sentimiento. Recuerde, 'la optimización prematura es la raíz de todo mal '... Si pasa todo el tiempo preocupándose por las pequeñas diferencias de velocidad, nunca logrará hacer nada. Constrúyalo de la manera que funcione para usted, y luego ** si ** tiene problemas, refactorícese desde allí. Pero la mejora de rendimiento más grande que puede hacer es la transición de un estado que no funciona a uno en funcionamiento. Todo lo demás palidece en comparación ... – ircmaxell

+1

Saludos, el enlace es muy útil y su punto es muy cierto, es muy difícil no quedar atrapado en querer el código prefecto y nunca realmente liberarlo: D – Rob

+4

código de mantenimiento de la OMI es mucho más importante que el código de alto rendimiento. Piénsalo. Es más barato tirar más hardware a un problema de lo que está lanzando a más desarrolladores. Esa es una de las razones por las que PHP es tan popular ... Ahora, siempre hay una compensación, así que no estoy recomendando ignorar el rendimiento, pero no intente micro-optimizar si no sabe si existe algún problema. – ircmaxell

1

considerar el uso de array accessors.

class Record implements ArrayAccess { 

    /** 
    * @see ArrayAccess::offsetExists() 
    * 
    * @param offset $offset 
    */ 
    public function offsetExists($offset) { 

    } 

    /** 
    * @see ArrayAccess::offsetGet() 
    * 
    * @param offset $offset 
    */ 
    public function offsetGet($offset) { 
     //fetch and cache $result 

     return $result[$offset]; 
    } 

    /** 
    * @see ArrayAccess::offsetSet() 
    * 
    * @param offset $offset 
    * @param value $value 
    */ 
    public function offsetSet($offset, $value) { 

    } 

    /** 
    * @see ArrayAccess::offsetUnset() 
    * 
    * @param offset $offset 
    */ 
    public function offsetUnset($offset) { 

    } 
+2

Y eso es diferente, ¿cómo? Solo está intercambiando cuatro métodos mágicos por otros cuatro métodos mágicos ... – ircmaxell

+0

@ircmaxell Los métodos de interfaz no son métodos mágicos. Aunque no puedo hacer una copia de seguridad con números, afirmo que estos se ejecutarán más rápido que confiar en los interceptores – Gordon

+0

@Gordon: Es más lento, verifique el enlace en la respuesta anterior. Y sí, aunque no es un "método mágico" en sentido estricto, es mágico en el sentido de que la interfaz permite la funcionalidad mágica (la capacidad de usar funciones básicas y construcciones de lenguaje en el objeto) ... – ircmaxell

1

hice algunas pruebas con métodos mágicos PHP y operaciones nativa get/set (en una propiedad pública)

Los resultados:

métodos mágicos son mucho más lento que el acceso nativo. PERO el tiempo de acceso sigue siendo tan pequeño, que no hará una diferencia en el 99.9% de todos los casos.

Incluso si lo hace de 1 millón de accesos método mágico dentro de una petición, todavía sólo toma aproximadamente 0,1 segundos ...


"sólo lectura" significa acceso a través de métodos mágicos. La imagen muestra los resultados de PHP 5.5.9 y PHP 7.0.

benchmark results

Aquí es el guión de referencia: https://github.com/stracker-phil/php-benchmark/blob/master/benchmark.php

Cuestiones relacionadas