Revisiting the “Cookieless Domain” Recommendation

It’s always nice to see someone question established beliefs, specially on the highly evolving world of web development.

Jonathan Klein from Etsy revisits the “cookieless domain” recommendation for serving static assets (CSS in particular) and analyses the pros, cons and the importance of taking DNS lookups and latency into consideration.

Revisiting the “Cookieless Domain” Recommendation

El nuevo PHP

Aunque por mucho tiempo PHP ha sido considerado el patito feo de los lenguajes de programación, lo cierto es que desde que hace aproximadamente un año pudimos confirmar la sospecha de que es por lejos el lenguaje más popular en la web: según cifras de Google, se trata del lenguaje que está tras el 75% de la web.

Pero esta cifra no es la única buena noticia para quienes utilizamos este lenguaje, ya existen varias señales ligadas a su desarrollo y utilización que auguran un futuro cada vez más brillante, al punto que en varios medios se habla del renacer de PHP.

Continue reading “El nuevo PHP”

Herramientas para la optimización de MySQL

En un trabajo de optimización es necesario revisar cientos de factores que pueden estar influyendo en el funcionamiento de un sistema, entre los que la base de datos puede tener un rol clave. Afortunadamente existen múltiples herramientas automatizadas que nos pueden facilitar este trabajo, o al menos darnos un punto de partida para poder ajustar las configuraciones de MySQL de modo de sacar el máximo provecho al hardware que estás utilizando.

  • mysqltuner es una de las alternativas más conocidas y por lo mismo se puede encontrar en los repositorios de varias distribuciones, pero en caso que no sea así la puedes descargar desde su repositorio en GitHub. Dado que se trata de un “simple” script en Perl, basta bajarlo y otorgar permisos de ejecución para obtener una serie de datos críticos y sugerencias de optimización, orientadas tanto a mejorar el performance como la estabilidad.
  • mysql-tuning-primer funciona de modo similar, y lo puedes descargar desde su página de proyecto en Launchpad. En este caso es un script en bash, que a partir de las variables de status de MySQL intenta generar recomendaciones sensatas para optimizar el servidor. Además de las sugerencias de configuración, en varios casos agrega información adicional para comprender de mejor forma el contexto de los ajustes en caso que no tengas un conocimiento muy acabado de las variables en las que indica modificaciones.

Aunque ambas herramientas entregan información muy valiosa para realizar mejoras en el funcionamiento de tu base de datos, es fundamental complementarlas con un conocimiento acabado de cada una de las variables de configuración y el funcionamiento de la aplicación para abordar exitosamente la tarea de optimización.

Pruebas de performance, carga y de estrés

Una ayuda-memoria breve, para tener claros tres conceptos que a veces se confuden:

  • Una prueba de performance tiene como objetivo eliminar “cuellos de botella” en la ejecución de una aplicación y poder determinar una medida aceptable para su funcionamiento, por ejemplo, cuál es un tiempo de respuesta aceptable y la carga esperada en relación al número de usuarios concurrentes. Con estas metas definidas, comienza un proceso de poder detectar y optimizar los procesos donde se entrampa la ejecución del software.
  • En un test de carga, el proceso consiste en aumentar progresivamente la carga en el sistema, a través de herramientas automatizadas; en una aplicación web esto significa examinar cómo se comporta la aplicación con distintos niveles de usuarios concurrentes. El objetivo principal es asegurar que la aplicación alcanza los objetivos de performance establecidos en las pruebas de performance.
  • Las pruebas de estrés buscan forzar una falla del sistema a través del consumo excesivo de sus recursos; con el objetivo de examinar cómo falla y vuelve a su funcionamiento normal.

A partir de esto, podemos entender que estos tres tipos de pruebas apuntan a dominios y objetivos distintos: el primero, a la optimización (que la aplicación funcione rápido), el segundo a la resistencia (que la aplicación funcione rápido aun con muchos usuarios), y el tercero, a la recuperabilidad (que la aplicación continúe funcionando incluso después de que el servidor se haya reiniciado o se haya agotado su espacio en disco).

En el proceso de optimización, además de las mejoras propias al funcionamiento de la aplicación, debemos considerar una serie de mecanismos alternativos para poder asegurar su buen funcionamiento, tales como:

  • Optimización del servidor de base de datos (por ejemplo, caché de consultas, contemplar un/os servidor/es dedicado/s para bases de datos, etc).
  • Caché de objetos para evitar lecturas desde base de datos (memcached, APC, etc).
  • Utilización de sistemas de caché estático (nginx como proxy inverso, Varnish, etc).
  • Escalar vertical u horizontalmente los servidores web (a través de un balanceador de carga).

… aunque como leí por ahí, hay que tener en cuenta que optimizar para performance (solamente para performance) no es lo mismo que optimizar para carga (es decir, pueden existir algunas alternativas que permitan servir una mayor cantidad de usuarios simultáneos, pero no necesariamente de forma más rápida para cada uno de ellos).

Más información en: Agile Testing: Performance vs. load vs. stress testing

Foto: Shell Games por Lazlo Ilyes

Mejorar la velocidad de carga de dumps de MySQL con InnoDB

Un tip rápido: si notas que al importar dumps de bases de datos que utilizan InnoDB la carga es mucho más lenta que en bases de datos con MyISAM, puedes mejorar bastante la velocidad de carga con algunas opciones de mysqldump:

  • En primer lugar, está la opción --opt, que habilita una serie de alternativas que hacen que la importación sea bastante rápida…
  • … pero si por alguna razón debes utilizar alguna opción no predeterminada al crear el dump (en mi caso, era --skip-extended-insert), puedes utilizar --no-autocommit, que hace que la importación sea tan rápida como utilizando MyISAM

¿La explicación?

Como InnoDB es transaccional, lleva un registro de cada operación.

Con la primera alternativa, sólo se ejecuta un INSERT por tabla, por lo que no necesita realizar muchas operaciones de registro.

Con la segunda alternativa, a pesar que se indican muchos INSERT, sólo se confirman los cambios una vez por tabla ya que los bloques de INSERT van rodeados con set autocommit=0; y un único COMMIT al final.

Sam’s ultimate web performance tool and resource list

While preparing for my talk at Codemania I started filling my slides with links, clearly not something that scales. So, instead, here is a big list of interesting tools and resources that can help you journey through the murky waters of web performance.

Originally posted on March 28, 2012 at 06:36PM at Sam’s ultimate web performance tool and resource list

Trabajando con datos serializados en WordPress

WordPress permite trabajar con datos serializados en opciones y meta datos de entradas, comentarios y usuarios, lo que puede ser una muy buena opción al trabajar con datos complejos como arrays u objetos.

Supongamos el siguiente escenario: estás desarrollando un metabox para un tipo personalizado de contenido que representa a personas, y en el que debes agregar información de contacto como teléfono, correo electrónico, dirección, etc; la que se mostrará junto a cada persona como una ficha.

Una opción para guardar estos datos sería recurrir a alguna convención de nombres de modo que cada dato se almacena como una fila en la tabla $wpdb->postmeta; algo como _persona_telefono, _persona_email, _persona_direccion, etc. Luego, al mostrar los datos podríamos hacer una consulta como SELECT * FROM $wpdb->postmeta WHERE post_id = $post_id AND meta_key LIKE '_persona%'.

Sin embargo, una mejor alternativa en este tipo de casos sería recurrir a la utilización de datos serializados, ya que nos permitirán guardar en un solo campo una estructura compleja de datos como un array (uni o multidimensional) o un objeto; lo que nos puede facilitar de forma importante varias tareas si planificamos con cuidado nuestra estructura de datos.

Continue reading “Trabajando con datos serializados en WordPress”

Usando la API de Transients en WordPress

WordPress tiene varias API’s muy interesantes y prácticas, aunque no todas ellas son igual de conocidas.

Una de las que he venido a conocer más recientemente es la API de Transients, que permite trabajar con datos temporales de un modo simple y estándar, lo que resulta ideal si quieres crear una caché de datos con un tiempo de expiración, por ejemplo, al realizar consultas muy complejas a la base de datos o al obtener datos desde una fuente externa.

Esta API trabaja de forma muy similar al API de opciones, pero con el agregado de un tiempo de expiración de los datos, tras el cual WordPress eliminará la información almacenada en la base de datos. En nuestro plugin/widget/clase/función podremos implementar los métodos necesarios para chequear si existe el contenido cacheado o bien refrescar los datos, según sea necesario. La API implementa tres funciones que nos permiten guardar, obtener, o eliminar los datos, respectivamente:

/**
 * Guardar datos a la base de datos
 * @param string $transient Nombre del transient
 * @param mixed $value Datos que se guardarán. WordPress detecta si es un string o datos más complejos, y en este caso los guardará automáticamente como datos serializados
 * @param int $expiration El tiempo de expiración, en segundos.
 * @return boolean Verdadero o falso, de acuerdo a si la operación se ha realizado
 **/
set_transient($transient, $value, $expiration);

/**
 * Obtener datos
 * @param $transient string Nombre del transient.
 * @return mixed Los datos del transient, ya sea como string, como array u objeto si eran datos serializados, o bien falso si los datos no existen.
 **/
get_transient($transient);

/**
 * Borrar datos, para cuando se quieran borrar antes del tiempo de expiración
 * @param $transient string Nombre del transient
 * @return boolean Verdadero o falso, de acuerdo a si la operación se ha realizado
 **/
delete_transient($transient);

De este modo, en nuestro plugin/widget/función/etc. sólo nos bastará comprobar si los datos ya existen y refrescarlos en caso que sea necesario:

function mi_funcion(){
	global $wpdb;
	$transient_data = get_transient('mis_datos');
	if ( ! $transient_data ) {
		// Obtener los datos
		$get_data =  json_decode( file_get_contents( 'http://search.twitter.com/search.json?q=from%3Afelipelavinz' ) );
		// Guardarlos en el transient
		if ( set_transient('mis_datos', $get_data, 3600) ) $transient_data = $get_data;
	}
	foreach ( $transient_data as $key=>$val ) {
		// Procesar los datos
	}
}

Una buena manera de mejorar la performance de tus plugins/widgets/funciones.

Sitios web aún más rápidos

A propósito del post sobre la “sensación” de velocidad y los selectores eficientes que publicó recientemente Armonth en su blog, recordé una de las presentaciones de la Web 2.0 Expo en San Francisco de la que había visto sus diapositivas, y que hablaba más o menos del mismo tema.

La presentación estuvo a cargo de Steve Souders, quien trabaja en Google en iniciativas de código abierto y alta performance, es el creador de YSlow — una herramienta (plugin para Firebug) desarrollada por Yahoo! para medir la performance de un sitio — y especialista en sitios de alta performance.

Pueden ver la presentación en Slideshare o bien descargar la original desde la ficha técnica de su charla.