Cómo acelerar Smarty 5 veces en Lighttpd

En este artículo hablaremos de cómo se obtuvo un aumento de velocidad de 5 veces en un sitio web con Smarty sobre un servidor web Lighttpd. Esto se consiguió permitiendo al servidor Lighttpd acceso directo a los archivos almacenados en el caché y servirlos directamente desde allí, en lugar de llamar a Smarty.

¿Por qué es este enfoque mucho más rápido?

El motor de caché de Smarty realiza un gran trabajo compilando las plantillas en el momento adecuado, y esto produce un aumento sustancial de la velocidad comparado con la recompilación de la plantilla con cada petición de página.

No obstante, incluso cuando Smarty sirve páginas de su caché, hay una cantidad de trabajo extra añadido a cada petición comparado con el servidor web sirviendo directamente la página desde el caché. Esto es porque  PHP debe llamarse, la librería Smarty se debe incluir, y una pequeña cantidad de procesos deben ejecutarse dentro de Smarty antes de que la página en caché sea servida.

¿Es esta técnica de caché adecuada para cualquier situación?

En casos en los que la vida del caché debe ser muy corta debido a cambios frecuentes en los datos que deben mostrarse, el enfoque de este artículo puede resultar inviable. No obstante, en estos casos puede ser todavía posible un proceso forzado que borre el caché cuando los datos cambian, en lugar del trabajo extra añadido de comprobar si ha habido cambios en cada solicitud de página. Esta aproximación de borrado forzado del caché reduce el coste al valor más bajo posible, así que si el rendimiento es de vital importancia, tiene todo el sentido ensayar esta técnica.

Cuando los cambios en los datos ocurren infrecuentemente, una combinación de vaciar el caché en intervalos programados más un método para forzar manualmente la recompilación de páginas específicas es adecuada, y un compromiso que vale la pena para aumentar el rendimiento.

Notas sobre la Implementación

Ya que Smarty es una librería muy flexible, cada implementación es única. Por tanto, en lugar de intentar abordar la cuestión de cómo implementar el caché en Lighttpd,  explicaremos una forma de hacerlo que resultó adecuada en la práctiica.

Esta era la configuración de Lighttpd para el sitio web antes de implementar el caché. Tenía unas pocas reglas de re-escritura de URLs, de forma que las peticiones de ficheros (htm|html) se pasaban directamente a index.php. Este fichero actúa como un manejador para determinar la plantilla Smarty que debe cargarse, permitiendo además el uso de URLs amigables.

Código:
$HTTP[“host”] == “www.site.com” {

server.document-root = “/var/www/site/html”
url.rewrite = (

“/(.*)\.(htm|html)(\?.*)??$” => “/index.php?p=$1”,
“/(.*)/(\?.*)??$” => “/index.php?p=$1”,
“/(.*)/(.*)/$” => “/index.php?p=$1/$2”

)

}

Y después de implementar el caché, esta es la configuración del servidor Lighttpd:

Código:
$HTTP[“host”] =~ “www.site.com” {

server.document-root = “/var/www/site/html”
magnet.attract-physical-path-to = (“/var/www/site/html/rewrite.lua”)

}

Más abajo está el código de rewrite.lua (referenciado más arriba en la configuración de Lighttpd), que implementa lighttpd mod_magnet para manejar las reglas de re-escritura de URLs. Comprueba el sistema de ficheros para determinar si existe un fichero en caché, y, si es así, sirve ese fichero. En otro caso, re-escribe hacia el manejador index.php, de forma que Smarty puede generar un nuevo fichero para el caché.

La variable cache_path en el script rewrite.lua almacena la carpeta del caché de Smarty ( $smarty->cache_dir ), además de $smarty->cache_id (en este caso es blank (vacío); asegúrese de agregarlo a la variable cache_path como una subcarpeta del cache_dir de Smarty correspondiente a su instalación)

Código:
cache_path = "/var/www/site/tmp"
cache_code = "compile"
-- construir la página y guardarla en el caché del sistema de ficheros
function cache_gen()
lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. "/index.php"
lighty.env["uri.query"] = "p=" .. string.gsub(lighty.env["uri.path"], "\.(htm|html)$", "")
--print ("CACHE: " .. lighty.env["uri.query"])
end
-- cargar la copia desde al caché del sistema de ficheros
function cache_load()
lighty.env["physical.path"] = cache_path .. lighty.env["uri.path"]
--print ("LOAD: " .. cache_path .. lighty.env["uri.path"])
end
-- añadir el fichero index si se solicita un listado del directorio
if(lighty.env["uri.path"] == "" or string.find(lighty.env["uri.path"], "/", -1)) then
lighty.env["uri.path"] = lighty.env["uri.path"] .. "index.html"
end
-- procesar las peticiones htm|html
if(string.find(lighty.env["uri.path"], "htm", -4)) then
exists = lighty.stat(cache_path .. lighty.env["uri.path"])
cache_code_passed = false
if(lighty.env["uri.query"] ) then
cache_code_passed = string.find(lighty.env["uri.query"], cache_code)
end
if(exists and not cache_code_passed) then
action = cache_load()
else
action = cache_gen()
end
end

En este punto, Lighttpd está re-escribiendo todas las solicitudes y enviándolas al manejador index.php ya que no encuentra una imagen caché en la carpeta cache_path. Ahora hay que trabajar con el manejador index.php de forma que Smarty guarde los ficheros HTML compilados en el cache_path definido en rewrite.lua. Para hacer esto, podemos escribir una función personalizada manejadora del caché para Smarty, e incluirla en el fichero index.php. Hasta aquí, la implementación de Smarty se parece a:

Código:
<?php
require "../includes/smarty/Smarty.class.php";
$smarty = new Smarty;
$smarty->template_dir = 'templates';
$smarty->compile_dir = 'compile';
$smarty->cache_dir = '/var/www/site/tmp';
$smarty->caching = true;
$smarty->force_compile = true;
$smarty->compile_id = '';
$smarty->cache_handler_func = 'server_rewrite_cache_handler';
function server_rewrite_cache_handler($action, &$smarty_obj, &$cache_content, $tpl_file=null, $cache_id=null, $compile_id=null, $exp_time=null)
{
$cache_file = $smarty_obj->cache_dir . '/' . $compile_id . $cache_id;
if(!is_file($cache_file)) {
$base_file = basename($cache_file);
$base_dir = dirname($cache_file);
if(!is_dir($base_dir)) mkdir($base_dir, 0777, true);
}
    switch ($action) {
        case 'read':
         if(!is_file($cache_file)) return false; else return true;
            break;
        case 'write':
         return file_put_contents($cache_file, $cache_content);
            break;
        case 'clear':
         return @unlink($cache_file);
            break;
        default:
            return false;
            break;
    }
}
$_p = $_REQUEST['p']; // detectar el path del fichero solicitado para guardar la copia en caché con el nombre y path correctos
$page = ''; // lógica aquí para detectar la plantilla Smarty correcta que debe mostrarse
$smarty->display($page, $_p);
?>

Lo principal aquí es que el caché está habilitado, cada petición recompila la plantilla, el compile_id es blank (vacío), y el cache_dir coincide con lo que está puesto en cache_path (en rewrite.lua).

La funcción server_rewrite_cache_handler() sobre-escribe la lógica por defecto de Smarty para leer/escribir/vaciar el caché de forma que el fichero se guarda en la estructura de directorio correcta que coincide con la solicitud que fue re-escrita desde Lighttpd.

La última cosa es deshabilitar algunas líneas de código en el fichero smarty/internals/core.write_cache_file.php, ya que por defecto Smarty añade algunos datos serializados a la cabecera de los datos del caché que pasa a nuestra función personalizada para manejar el caché. Los cambios se muestran más abajo, y ocurren sobre las líneas 65 y 66 del fichero core.write_cache_file.php.

Código:

#$_cache_info = serialize($smarty->_cache_info);
#$params[‘results’] = strlen($_cache_info) . “\n” . $_cache_info . $params[‘results’];

Esto es todo. Debería experimentar una drástica mejora en la velocidad y rendimiento del servidor en este punto.

Etiquetas: , , , , ,

Responder

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


A %d blogueros les gusta esto: