PHP y Xdebug

Hace unas semanas encontré respuestas a preguntas que me planteé hace años acerca de PHP.

Unas de las primeras cosas que aprendemos cuando conocemos PHP, es que al trabajar en la web, el motor funciona con ciertos límites. Límite de tiempo de ejecución (30 segundos por omisión) y límites de uso de memoria (16M por omisión en mi caso).

Lo malo no es que existan límites, todo lo contrario, en el caso de una aplicación web, de naturaleza concurrente, es necesario que lo que hace un usuario no pase a llevar lo que hace otro, cuidando de pasada los recursos de la máquina servidora. Sería nefasto programar mal un ciclo, de tal modo que en ciertas condiciones se vuelva infinito y además la ejecución no parara nunca. También sería catastrófico que tan solo 2 usuarios ejecutando un script terminaran haciendo colapsar el servidor por uso excesivo de memoria. El problema está cuando estamos desarrollando y olvidamos estos límites, lamentablemente en las situaciones más incomodas es cuando se manifiestan, por ejemplo al extraer demasiados datos desde una base de datos, o al hacer una operación muy larga en uso de disco (por ejemplo copiar muchos archivos de un lado a otro), o al leer un archivo muy grande, etc…

Entonces las preguntas que me hice hace años fueron algo así:
¿Como puedo saber cuanto tiempo demora la ejecución de mi script? ¿Como puedo saber cuanto que funciones/procedimientos son las más lentas? ¿Como puedo saber cuanta memoria consume mi script en ciertas condiciones? ¿Como puedo saber cuanta memoria consume una operación?

RESPUESTA: Xdebug

Xdebug es una extensión para PHP (como la GD, BZip2, Mysql, …) pero funciona como una extensión algo especial.

Primero lo primero: Hacerla funcionar

En *Ubuntu afortunadamente se encuentra en los repositorios. También se encuentra en Debian Lenny con el mismo nombre:

sudo apt-get install php5-xdebug

También es conveniente que en este punto, instalemos las otras herramientas, si es que no están instaladas. Entre ellas, podemos además instalar kcachegring (advertencia para los gnomeros: kcachegrind por su K inicial, nos dice que ocupa librerías de KDE), una aplicación gráfica que nos sirve para ver los archivos cachegrind.out.* que genera el “profiler” de xdebug (si es que lo queremos ocupar). El paquete sysvconfig agrega el comando “service” que ayuda para acortar un poco las llamadas a los scripts de se control de servicios.

sudo apt-get install sysvconfig apache2 libapache2-mod-php5 php5-xdebug kcachegrind

Una vez instalado el servidor Apache, PHP, la extensión Xdebug y Kcachegrind

Debo confesar que intente instalarla en Windows Vista también, pero me fue imposible, el binario precompilado no funcionó ni a palos. Tal vez lo intente más adelante con XP virtualizado, o compilando la librería.

Configurar la extensión

Las versiones nuevas de PHP en Linux permiten tener archivos de configuracion ( *.ini ) separados. En *ubuntu existe la carpeta /etc/php5/apache2/conf.d

Luego de la instalación de xdebug, se crea un archivo /etc/php5/apache2/conf.d/xdebug.ini que simplemente carga la librería de la extensión.

En ese mismo archivo (si no es posible, puede agregar la configuración directamente al php.ini), podemos agregar las directivas para configurar el profiler y el depurador remoto:

Antes:

zend_extension=/usr/lib/php5/20060613+lfs/xdebug.so

Despues:

zend_extension=/usr/lib/php5/20060613+lfs/xdebug.so

xdebug.profiler_enable = On
xdebug.profiler_output_dir = /tmp
xdebug.profiler_output_name = cachegrind.out.%p

xdebug.remote_enable=true
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.remote_handler=dbgp

Acá están las mismas opciones adicionales para el php.ini (o xdebug.ini).

Ok, esto hará que los archivos del profiler se guarden con en la carpeta /tmp con nombre cachegrind.out.%p donde %p es el número de proceso que está ejecutando PHP. Si se llamo desde el navegador web, correspondera al número de proceso de Apache. Además, si nuestro apache está corriendo como multihilo, el número corresponderá la hilo que procese el script con PHP.

¿Que se puede hacer con Xdebug?

Tiene varias características que facilitan el desarrollo, por ejemplo:

  • Reemplaza los mensajes de error predeterminados de PHP, por otros con mayores detalles, que además de mencionar el tipo de error y la linea donde ha ocurrido, incluyendo una traza con el anidamiento de las funciones llamadas, desde “{main}” hasta el punto donde ocurrió el error, donde además muestra el nombre de la cada función llamada, el “tiempo” en el que ocurrió y cuanta memoria se ha consumido hasta ese punto.

    Script de Ejemplo | Resultado:

  • Reemplaza algunas funciones naturales de PHP para dar mayor información. Por ejemplo la función var_dump() que nos muestra el tipo y contenido de un dato, ahora colorea de distinta manera cada tipo. También se puede configurar Xdebug para que solo muestre cierto nivel de anidamiento cuando queremos ver un array o un objeto, es decir, si un array tiene 10 dimensiones de profundidad, puedo configurarlo para mostrar hasta 3, para así facilitar la legibilidad. Es usual ocupar var_dump en varias partes mientras se desarrolla cuando no estamos seguros de que valor tiene una variable.

    Script de Ejemplo | Resultado:

  • Incorpora funciones nuevas, que permiten ver detalles antes desconocidos. Por ejemplo:
    • xdebug_time_index( ) Retorna un float con el valor del tiempo de ejecución desde “{main}”, es decir desde que comenzó a correr el script.
    • xdebug_memory_usage( ) Retorna un entero con el valor del uso de memoria actual.
    • xdebug_peak_memory_usage( ) Retorna el pick de memoria ocupada, es decir, el máximo (por supuesto, hasta antes de llamar la función).
    • xdebug_call_* Son varias funciones que retornan datos sobre “el lugar” donde se esta ejecutando algo. Por ejemplo, podemos introducir xdebug_call_class en una función para luego poder averiguar” desde que clase” se llamo a esa función, xdebug_call_line para saber en que linea y así… Más detalles en la documentación básica de xdebug.
  • Perfilar el código. Quienes hayan trabajador con C y otros lenguajes, tal vez conocen valgrind. Valgrind es una herramienta que sirve para perfilar un programa en C, compilado con opciones de depuración. De esta manera se puede hacer un análisis de rendimiento del programa. Xdebug puede generar archivos del mismo formato que valgrind, de tal modo que podemos verlo con cualquier herramienta compatible, como Kcachegrind.

    Script de Ejemplo | Resultado: (notece que no es un navegador sino Kcachegrind)

  • Integrar el depurador con un IDE: Es una característica que no he explotado a fondo, pero al igual que otros lenguajes como C, xdebug permite “ver” el funcionamiento del programa en tiempo real. Para ello implementa un protocolo común llamado dbgp (el mismo que se ocupa con C/C++ y otros lenguajes). La extensión actua como un servicio, y el IDE como un cliente (notence las líneas ocupadas para configurar en el xdebug.ini)

Más adelante, exploraré más características de xdebug, al menos con las que mostré acá, ya es suficiente para trabajar mejor.

To be continue…

Actualización: El día Jueves 26 de Junio del 2008 a las 22 horas, poco después de publicar este artículo, comenté acerca de PHP y Xdebug en el chat de irc.debianchile.cl => El log (registro) pueden verlo acá (gracias por invitar :D).

OpenSolaris 2008.05: es bonito pero…

No se si es porque estoy muy acostumbrado a Linux, en suma con mi inexperiencia con Solaris (salvo este intento), pero creo que no podría sacar una evaluación “positiva” a la prueba que hice de OpenSolaris Indiana.

Mi primera impresión fue que es un Sistema bastante “bonito”, incluso llegue a sentir como si estuviera instalando Ubuntu. El instalador es bastante facil de entender, realmente no tuve ninguna dificultad para instalarlo.

Seguir leyendo OpenSolaris 2008.05: es bonito pero…

Arreglar el brillo cuando se pone rebelde

Hoy no se porque por esas mañas, azar, destino o que se yo… Mi Notebook dejó de responder a las teclas Fn+F7 y Fn+F8 para bajar o subir el brillo.

Despertó con una horrible pantalla con brillo 0.

Buscando y navegando, aun no logro dar con la fuente del problema de las teclas, pero encontré una buena solución parche, ocupando la amiga consola:

sudo su -c 'echo -n 100 > /proc/acpi/video/VGA/LCD/brightness'

Donde 100 es el porcentaje de brillo según los valores permitidos, que se pueden ver acá:

gon@gon:~$ cat /proc/acpi/video/VGA/LCD/brightness
levels:  100 60 20 28 36 44 52 60 68 76 84 92 100
current: 100

Aun no doy con la solución definitiva :S