Inicio

Pensamientos

Ver entrada

Avatar de jesus   jesus   20/06/2011 a las 09:13
Desarrollo en PHP: algunos pensamientos y optimización del rendimiento
Foto: Desarrollo en PHP: algunos pensamientos y optimización del rendimiento

Introducción

Como ingeniero técnico no lo he hecho del todo bien: tendría que haber evitado (¿desde el principio?) el tema de la programación. Por varios motivos. El primero que la programación o cualquier otro trabajo excesivamente técnico es muy exigente en cuanto a actualización de conocimientos, amén de que en el futuro o evolucionas, o no podrás competir con nuevas generaciones en cuanto al binomio conocimientos - coste para la empresa.

El segundo motivo es que se corre el riesgo de caer en trabajos monótonos, mal remunerados y compartidos con gente sin formación en absoluto. Y más si la tecnología en la que te encasillas es PHP, donde, por la facilidad de comenzar y hacer cualquier cosa en dicho lenguaje de programación está al alcance de un niño de 10 años. Y cuando digo "cualquier cosa", me refiero a basura.

Desarrollar en PHP

Pero vamos a centrarnos en los problemas que tiene desarrollar en PHP.

El principal problema, más allá de toda duda, es la falta de preparación de quien suele trabajar con dicha tecnología. Las clases de ingeniería del software y una capacidad de análisis de los problemas no los puede suplir cualquiera con copia y pega de Internet y experiencia propia. Alguno podrá, pero son una minoría. Y he conocido a alguno.

PHP ofrece algunas ventajas sobre algunos lenguajes, al ser interpretado. La rapidez al pasar de desarrollo a pruebas y explotación a veces es notable. Se escribe el código y se ejecuta. En Java el asunto es un poco más laborioso, y en el penoso caso de que estemos haciendo remiendos a última hora, apagando algún fuego, esto puede ser un poquito menos desesperante. Y como en PHP se hace la mayoría de las chapuzas...

Además PHP se ejecuta en principio algo más rápido que Java. Hay numeras pruebas de rendimiento (benchmark en inglés, y si alguien necesita que se lo traduzcan también, rendimiento se convierte en performance) en las que PHP supera ligeramente a Java en este aspecto. Esto puede resultar atractivo a más de uno.

La mayoría de las críticas hacia PHP, sin embargo, recaen sobre dos temas importantes. La orientación de PHP a objetos, y que no es un lenguaje tipado. Lo primero ha ido mejorando bastante en los últimos años, con la versión 5 del lenguaje, llegando a poder decirse que con PHP se puede hacer programación a objetos relativamente seria (si nos ponemos estrictos, ni siquiera Java sería estrictamente orientado a objetos, se salvaría Smalltalk y poco más...). La cosa ha llegado hasta el punto de que ya hasta se puede hacer uso de espacios de nombres (namespaces), ahora hasta parece un lenguaje "serio".

Respecto a que sea tipado o no tipado, hay un poco de diferencia de opiniones. Lo que para muchos puede conducir a un diseño errático y poco claro, abonando el campo para la ya florida falta de rigor en esta tecnología, para otros es una característica de lo más conveniente. Hay conversión de tipos (casting) implícita y explicita, lo que deja también abierta la forma de programar de cada uno. A mí personalmente me parece mucho peor la manera en la que se tratan las codificaciones de cadenas, un tanto oscurantista hasta ahora, pero que con el advenimiento de PHP 6 se supone que esto va a mejorar mucho-bastante. Aún así, precisamente es en este punto donde se han generado algunas discrepancias en el proyecto de PHP, creándose ahora dos ramas oficiales del lenguaje, según cómo se afronta el tema de la codificación. Pero al menos en PHP 6 ya se puede saber en qué está codificado un texto, todo un avance, vaya...

Otra carencia natural de PHP era la falta de paquetes de distribución de aplicaciones. Desde hace un tiempo existen unos paquetes denominados Phar (que personalmente no he probado), y que vendrían a ser algo equivalente a los Jar de Java. Bueno, la cosa promete, pero hasta que no lo pruebe no puedo decir nada. En cualquier caso, siempre es bienvenido cualquier cambio a mejor en cuanto a la distribución de aplicaciones al cliente.

Respecto a si desarrollar en POO o en estructurada, hay que señalar las ventajas de cada uno de los paradigmas. Estructurada permite producir resultados antes, y en principio de mejor rendimiento en cuanto a uso de recursos del servidor. La programación orientada a objetos, sin embargo, permite hacer un diseño mucho más robusto, claro y escalable, siendo a su vez la forma más adaptable a un desarrollo en equipo. Quizás una aplicación desarrollada con objetos despegue algo más tarde, y quizás consuma algo más de recursos, pero al menos se puede mantener y hacer cambios de manera más controlada, fácil, y menos traumática.

Y hablando de aplicaciones en PHP, y orientación a objetos. Se hecha mucho de menos persistencia de objetos. Sí, se pueden serializar objetos y luego "despertarlos", pero no es lo mismo que por ejemplo tener objetos que corran a nivel de aplicación o de servidor independientemente de que se haya creado o no un hilo para antender una petición HTTP. Si eso se pudiera hacer en PHP, entonces sí que podríamos hacer cosas realmente interesantes.

Optimización

Una de las pegas del desarrollo orientado a objetos en PHP es como digo la supuesta pérdida de rendimiento (pero a medida que un sistema se hace más grande, me gustaría ver cuál de los dos paradigmas gana en escalabilidad). Sin embargo, estamos hablando, por lo general de tiempos imperceptibles, y que sólo hacen notarse cuando hay un cuello de botella que afecta a los procesos de manera indirecta... y ahí, de nuevo, es donde entra un buen diseño.

  1. Un primer acercamiento al problema del rendimiento de una aplicación (a la que ya hemos intentado hacer un buen diseño pero sigue presentando problemas o simplemente queremos potenciar) es revisar las consultas a base de datos. Doy por supuesto que estamos hablando de MySQL, aunque no tendría por qué ser así.
    1. Hacer uso de índices. Ni pocos ni muchos, sino todos aquellos por los que se vayan a realizar consultas típicas o pesadas. Los índices agilizan mucho la respuesta, pero también consumen más memoria.
    2. Evitar los cruces "normales" de tablas a favor del uso de los JOIN. Son mucho más eficientes
    3. Evitar recuperar todos los campos en las consultas (SELECT *). Si hay que escribir distintos métodos con distintas consultas para cada conjunto de campos requeridos, se hace.
    4. Los resultados de un mysql_query no son una estructura de datos, como podría pensar más de uno, sino un objeto de tipo recurso (resource). Si nuestro servidor de base de datos no da más de sí en cuanto a memoria, es más que probable que nos hayamos olvidado de liberar los resultados, que se quedan en el servidor BDD, y no está en el servidor web como pudiera parecer. Conviene hacer mysql_free_result() cuando no vamos a usar los resultados
    5. No abrir conexiones de manera innecesaria. También conviene saber que al crear una conexión podemos forzar para que esta sea nueva o reutilizar una ya existente.
    6. Examinar el log de consultas lentas. MySQL nos ofrece la posiblidad de conocer aquellas consultas que se tomaron más tiempo del considerado necesario. Por defecto se llamará nombre_del_servidor-slow.log. Los programadores nos hacemos muchas pajas a nivel de código para ganar 30 milisegundos, cuando a lo mejor en una consulta mal hecha perdemos varios segundos
  2. A nivel de programación se pueden hacer muchas cosas para mejorar el rendimiento. En general seguir los principios que se estudian en metodología de la programación es un buen comienzo. Hacer uso de pocos componentes ajenos y pesados y más de componentes de desarrollo propio también. Pero veamos algunas cosas más
    1. Hacer uso de patrones de diseño: son soluciones estándar que proveen soluciones más o menos óptimas a problemas comunes. He visto cómo hay gente que dice ser "profesor" (¿en qué?) que recomienda almacenar en variables globales información de alta incidencia al comienzo de la ejecución. ¿Esta gente no oyó nunca hablar de cosas como el Singleton?
    2. Definir las variables antes de usarlas. Parece de sentido común, ¿no? Ya, pero como PHP muchas veces no se queja... muchos programadores hacen uso de variables no declaradas o inicializadas, lo que relentiza la ejecución. Igualmente, revisar el código para ver si se utilizan todas las variables declaradas. Y en la medida de lo posible, reutilizar variables dentro de funciones
    3. Las variables globales implican una ejecución más lenta que las variables locales. Aparte de que su presencia evidencia un diseño caprichoso
    4. Uso de constantes para valores que siempre serán constantes en vez de declarar variables
    5. Ir limpiando las variables de vez en cuando: cuando estamos realizando procesos pesados, con bucles que tratan mucha información, o casi que en cualquier situación, conviene ir haciendo de vez en cuando unset() de las variables o posiciones de array que no vayamos a usar. Tener en cuenta que las declaraciones y ciertas asignaciones no deben de ir dentro de bucles, sino antes... que se ve cada cosa por ahí que quita el hipo
    6. Comillas simples en vez de comillas dobles. Las segundas evalúan en contenido de la cadena entrecomillada, pues podría contener alguna variable PHP, no siendo así en el primer caso.
    7. La estructura de control Switch es más pesada que la If. Del mismo modo la estructura For es más pesada que sus equivalentes.
    8. Llamar a las funciones mediante sus alias es más lento que llamar a las funciones directamente
    9. No utilices echo ni print (más lenta que echo) para pintar HTML que podría ser escrito directamente
    10. Todo lo anterior está muy bien, pero es nada comparado con un diseño inteligente y eficiente de la aplicación. Hay que pararse a pensar antes de escribir código
  3. Inisito en el hecho de que pararse a contar ciclos de CPU a estas alturas de la historia es un poco tonto, o al menos trivial si se compara con la vitalidad de un buen diseño o una buena configuración del servidor. Algunos ejemplos:
    1. Los ficheros fuente o script php no son ejecutados directamente; aunque sea un lenguaje interpretado, el código fuente se tiene que traducir a código objeto. Eso evidentemente tiene un coste en tiempo de CPU, así como el hacer la revisión léxica, revisar la sintáxis del código, optimizarlo... ¿Por qué hacerlo cada vez que hay una petición HTTP? Bueno, existe algo que se llamada cacheadores y optimizadores de código intermedio que funcionan razonablemente bien (a cambio de un cierto costo de memoria RAM en el servidor). El mejor ejemplo, o el más recomendable es el de APC. APC revisa el código fuente, lo optimiza (como hacen la mayoría de los compiladores) y convierte a código objeto. Después, lo almacena en memoria dinámica para sus futuros accesos. Esto mejora mucho los tiempos de respuesta del servicio web. Notablemente. Lo bueno de APC es que además es el que vendrá por defecto en PHP 6, un motivo más para decantarse por esta solución.
    2. Nuestro Apache y nuestro código es rapidísimo. Ejecuta un script en 30 milisegundos en vez de 60 milisegundos. Guau. ¿A quién le importa eso si luego la respuesta (típicamente un HTML) es pesada y tarda 1 segundo o más en llegar al cliente? Habilitar el envío en formato comprimido, como gzip por ejemplo, racionaliza mucho los tiempos de servicio web. Hay otras muchas cosas relacionadas con esto, pero las trataré en un futuro artículo
    3. Cacheo de imágenes, HTML, CSS, y JS. Sí, de muy diversas maneras, todo esto se puede hacer. A nivel de cliente concreto, y a nivel de servidor. De nuevo, trataré todo esto en posteriores artículos

Conclusión

PHP tiene menos componentes y menos clases desarrolladas que otras tecnologías, pero empieza a haber ya unas cuantas cosas hechas. El mayor problema es que es el lenguaje de los intrusos por excelencia. Gente sin preparación, sin estudios de ningún tipo, copiarán y pegarán tonterías que encuentran por Internet, la mayoría de ellas producto de gente que tampoco tiene estudios y sólo hace basura. Como contrapartida, al ser una tecnología que incurre en menos costes, por lo general, ahora en tiempos de crisis se está potenciando el uso de PHP para más y más proyectos.

Pero PHP permite también trabajar en serio, y su rendimiento no es tan malo como alguno podría creer. Trabajar con orientación a objetos es obligatorio en entornos de trabajo en grupo, o para proyectos "serios" que requieran un mínimo de diseño o vayan a sufrir un ciclo de vida prolongado o con cambios en sus requisitos. Es la obligación del ingeniero informático el que se sigan un mínimo los procedimientos de ingenería establecidos para el desarrollo de aplicaciones.

Respecto a la optimización del rendimiento de la aplicación, el enfoque correcto no es tanto a nivel de código sino a nivel de diseño de la arquitectura de la aplicación. Si bien, toda pequeña mejora en las consultas a la base de datos, o en el código, supondrán que el sistema será menos vulnerable ante situaciones de estrés del servidor. Por eso conviene hacer todas las cosas bien.

Hay muchos trucos para mejorar el rendimiento de manera sustancial de una aplicación. El almacenamiento de información o datos elaborados para ser utilizados directamente, en vez de elaborar la información o procesar los datos una y otra vez, es uno de ellos. Implementar sistemas de caché a distintos niveles es de vital importancia para grandes aplicaciones.

De todas formas, si eres ingeniero, estás desarrollando código como programador, o analista programador, o como cualquiera otra forma de esclavitud, y puedes permitírtelo, escapa. Aléjate de este mundo inmundo. O tendrás que tragar mierda todos los días, por un sueldo que no justifica las horas de estudio :D


Visto: 141 veces   Compartir en Menéame Compartir en Twitter Compartir en Facebook Compartir en Delicious

Imágenes relacionadas:

Niñas marroquinas Colores de Essaouira Pescadores y gaviotas en Essaouira Barca en Essaouira Pato y Photoshop Camara  Temperatura de color Torres de alta tensión III Essaouira

Aviso Legal Contacto Mapa del sitio Colabora Buscador Acerca de esta web Acerca del autor
DeSastreCajón, corriendo sobre jMVC