<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Aleph &#187; optimización</title>
	<atom:link href="http://aleph.llull.net/tag/optimizacion/feed/" rel="self" type="application/rss+xml" />
	<link>http://aleph.llull.net</link>
	<description></description>
	<lastBuildDate>Mon, 01 Aug 2011 08:48:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Como afecta el algoritmo al rendimiento (o resolviendo una pregunta de Google)</title>
		<link>http://aleph.llull.net/2010/04/11/como-afecta-el-algoritmo-al-rendimiento-o-resolviendo-una-pregunta-de-google/</link>
		<comments>http://aleph.llull.net/2010/04/11/como-afecta-el-algoritmo-al-rendimiento-o-resolviendo-una-pregunta-de-google/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 14:35:31 +0000</pubDate>
		<dc:creator>Eduard</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[algoritmo]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[optimización]]></category>
		<category><![CDATA[rendimiento]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://aleph.llull.net/?p=836</guid>
		<description><![CDATA[Tras nueve meses de sequía bloguera, vuelvo con un post bastante parecido al de &#8220;Exponenciación modular&#8221; (uno de los que más visitas tiene) que toca uno de los temas que me apasionan: el rendimiento de los algoritmos. Hace bastantes meses leí, via meneame, un post con 140 preguntas que (supuestamente) Google puede hacerte en una [...]]]></description>
			<content:encoded><![CDATA[<p>Tras nueve meses de sequía bloguera, vuelvo con un post bastante parecido al de &#8220;<a href="http://aleph.llull.net/2005/10/15/exponenciacion-modular/">Exponenciación modular</a>&#8221; (uno de los que más visitas tiene) que toca uno de los temas que me apasionan: el rendimiento de los algoritmos. Hace bastantes meses leí, <a href="http://www.meneame.net/story/140-preguntas-google-puede-hacer-entrevista-trabajo">via meneame</a>, <a href="http://blog.seattleinterviewcoach.com/2009/02/140-google-interview-questions.html">un post</a> con 140 preguntas que (supuestamente) Google puede hacerte en una entrevista de trabajo. Una de esas preguntas me llamó la atención, tanto que unos cuantos compañeros del trabajo la estuvimos comentando. Te pedían que escribieras un algoritmo muy simple:</p>
<blockquote><p>Dado un array A[N] de N números. Tienes que generar un array Ouput[N] de manera que Output[i] sea la multiplicación de todos los elementos de A[N] excepto A[i]. Por ejemplo Output[0] será la multiplicación desde A[1] hasta A[N-1] y Output[1] sera la multiplicación de A[0] y desde A[2] hasta A[N-1]&#8230;</p></blockquote>
<p>En ruby es tan sencillo como:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">n = A.<span style="color:#9900CC;">length</span>
Ouput = <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span>
  result = <span style="color:#006666;">1</span>
  n.<span style="color:#9900CC;">times</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>j<span style="color:#006600; font-weight:bold;">|</span> result <span style="color:#006600; font-weight:bold;">*</span>= A<span style="color:#006600; font-weight:bold;">&#91;</span>j<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> j == i <span style="color:#006600; font-weight:bold;">&#125;</span>
  result
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>El problema es que la pregunta continuaba con:</p>
<blockquote><p>&#8230; hazlo en O(n) &#8230;</p></blockquote>
<p>Ups, hay que repensarlo ya que el algoritmo anterior tiene dos bucles sobre N anidados por lo que es O(n<sup>2</sup>). Se me ocurrió hacerlo precalculando el producto de todos los elementos de A[N] y hacer que Output[i] = Total / A[i]. Así queda O(n).</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">product = A.<span style="color:#9900CC;">inject</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>total, n<span style="color:#006600; font-weight:bold;">|</span> total <span style="color:#006600; font-weight:bold;">*</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
Output = A.<span style="color:#9900CC;">collect</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>n<span style="color:#006600; font-weight:bold;">|</span> product <span style="color:#006600; font-weight:bold;">/</span> n <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Pero faltaba un último detalle de la pregunta:</p>
<blockquote><p>&#8230; sin el operador de división.</p></blockquote>
<p>Uff, ahora se pone interesante. Tras pensarlo un poco y escribir Ouput como una matriz de los elementos a multiplicar, ví un patrón que me podía servir. La matriz está formada por dos &#8220;triángulos&#8221; (perdón si el termino no es correcto. Hay algún matemático entre la audiencia?) que llamaremos L, resaltado en azul, y R, en rojo.</p>
<pre>Output[0]   = [<span style="color: blue;">   1</span>,<span style="color: red;"> A[1], A[2], ..., A[N-1]</span>]
Output[1]   = [<span style="color: blue;">A[0]</span>,    1,<span style="color: red;"> A[2], ..., A[N-1]</span>]
Output[2]   = [<span style="color: blue;">A[0], A[1]</span>,    1,<span style="color: red;"> ..., A[N-1]</span>]
...
Output[N-1] = [<span style="color: blue;">A[0], A[1], A[2], ...</span>,<span style="color: red;">      1</span>]</pre>
<p>Se me ocurrió que esos dos &#8220;triángulos&#8221; o productos parciales se podían calcular a la vez en un único bucle para usarlos posteriormente para calcular Ouput[i] = L[i] * R[i] ya que:</p>
<ul>
<li>L[i] = L[i-1] * A[i-1] para i &gt; 0 (L[0] = 1)</li>
<li>R[i] = R[i+1] * A[i+1] para i &lt; N-1 (R[N-1] = 1)</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">n = A.<span style="color:#9900CC;">length</span>
left,right = <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n, <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n, <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006666;">1</span>.<span style="color:#9900CC;">upto</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span>
  left<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">&#93;</span>        =  left<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">*</span> A<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  right<span style="color:#006600; font-weight:bold;">&#91;</span>n<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006600; font-weight:bold;">&#40;</span>i<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span> = right<span style="color:#006600; font-weight:bold;">&#91;</span>n<span style="color:#006600; font-weight:bold;">-</span>i<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">*</span> A<span style="color:#006600; font-weight:bold;">&#91;</span>n<span style="color:#006600; font-weight:bold;">-</span>i<span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
Output = <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span> left<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">*</span> right<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Bien, creo que al final lo hemos conseguido. Un algoritmo O(n) que no usa la división y que calcula los resultados según la formula indicada. Además, el algoritmo que usa la división tiene un problema: necesita que los elementos de A[N] sean <a href="http://es.wikipedia.org/wiki/Número_natural">números naturales</a> (es decir, que no puedan ser 0) mientras que los otros dos algoritmos no tienen esta restricción.</p>
<p>Si os estáis preguntando si realmente hay diferencia de rendimiento entre los tres algoritmos (principalmente el primero versus los otros dos), aquí tenéis un gráfico que lo demuestra.</p>
<p style="text-align: center;"><img class="size-full wp-image-854  aligncenter" title="Algorithms benchmark" src="http://aleph.llull.net/wp-content/uploads/bench.jpg" alt="" width="858" height="532" /></p>
<p>Como se puede ver, a medida que el tamaño del array A[N] crece los tiempos del primer algoritmo (<em>double loop</em>) crecen exponencialmente mientras que los otros dos (<em>division</em> y <em>triangles</em>) tienen un comportamiento lineal. <strong>Por tanto, si que hay diferencia, y mucha</strong>.</p>
<p>Los datos de benchmarking para generar el gráfico con el <a href="http://www.openoffice.org/product/calc.html">OpenOffice.org Calc</a> los he obtenido he usado el siguiente script que genera CSV.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#! /usr/bin/env ruby</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'benchmark'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> double_loop<span style="color:#006600; font-weight:bold;">&#40;</span>input<span style="color:#006600; font-weight:bold;">&#41;</span>
  n = input.<span style="color:#9900CC;">length</span>
  <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span>
    result = <span style="color:#006666;">1</span>
    n.<span style="color:#9900CC;">times</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>j<span style="color:#006600; font-weight:bold;">|</span> result <span style="color:#006600; font-weight:bold;">*</span>= input<span style="color:#006600; font-weight:bold;">&#91;</span>j<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> j == i <span style="color:#006600; font-weight:bold;">&#125;</span>
    result
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> division<span style="color:#006600; font-weight:bold;">&#40;</span>input<span style="color:#006600; font-weight:bold;">&#41;</span>
  product = input.<span style="color:#9900CC;">inject</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>total, n<span style="color:#006600; font-weight:bold;">|</span> total <span style="color:#006600; font-weight:bold;">*</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
  input.<span style="color:#9900CC;">collect</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>n<span style="color:#006600; font-weight:bold;">|</span> product <span style="color:#006600; font-weight:bold;">/</span> n <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> triangles<span style="color:#006600; font-weight:bold;">&#40;</span>input<span style="color:#006600; font-weight:bold;">&#41;</span>
  n = input.<span style="color:#9900CC;">length</span>
  left,right = <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n, <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n, <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#006666;">1</span>.<span style="color:#9900CC;">upto</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span>
     left<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">&#93;</span>       =  left<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">*</span> input<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    right<span style="color:#006600; font-weight:bold;">&#91;</span>n<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006600; font-weight:bold;">&#40;</span>i<span style="color:#006600; font-weight:bold;">+</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span> = right<span style="color:#006600; font-weight:bold;">&#91;</span>n<span style="color:#006600; font-weight:bold;">-</span>i<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">*</span> input<span style="color:#006600; font-weight:bold;">&#91;</span>n<span style="color:#006600; font-weight:bold;">-</span>i<span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>i<span style="color:#006600; font-weight:bold;">|</span> left<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">*</span> right<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
t = <span style="color:#006666;">1</span>_000
max_size  = <span style="color:#006666;">250</span>
step_size = <span style="color:#006666;">10</span>
&nbsp;
step_size.<span style="color:#9900CC;">step</span><span style="color:#006600; font-weight:bold;">&#40;</span>max_size, step_size<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>n<span style="color:#006600; font-weight:bold;">|</span>
  input = <span style="color:#CC0066; font-weight:bold;">Array</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>n<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#CC0066; font-weight:bold;">rand</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">100</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  t1 = <span style="color:#CC00FF; font-weight:bold;">Benchmark</span>.<span style="color:#9900CC;">realtime</span> <span style="color:#006600; font-weight:bold;">&#123;</span> t.<span style="color:#9900CC;">times</span> <span style="color:#006600; font-weight:bold;">&#123;</span> double_loop<span style="color:#006600; font-weight:bold;">&#40;</span>input<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  t2 = <span style="color:#CC00FF; font-weight:bold;">Benchmark</span>.<span style="color:#9900CC;">realtime</span> <span style="color:#006600; font-weight:bold;">&#123;</span> t.<span style="color:#9900CC;">times</span> <span style="color:#006600; font-weight:bold;">&#123;</span> division<span style="color:#006600; font-weight:bold;">&#40;</span>input<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  t3 = <span style="color:#CC00FF; font-weight:bold;">Benchmark</span>.<span style="color:#9900CC;">realtime</span> <span style="color:#006600; font-weight:bold;">&#123;</span> t.<span style="color:#9900CC;">times</span> <span style="color:#006600; font-weight:bold;">&#123;</span> triangles<span style="color:#006600; font-weight:bold;">&#40;</span>input<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{input.length};#{t1};#{t2};#{t3}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Por cierto, si a alguién se le ocurre otro algoritmo que lo ponga en los comentarios.</p>
]]></content:encoded>
			<wfw:commentRss>http://aleph.llull.net/2010/04/11/como-afecta-el-algoritmo-al-rendimiento-o-resolviendo-una-pregunta-de-google/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimizaciones en el blog</title>
		<link>http://aleph.llull.net/2009/05/24/optimizaciones-en-el-blog/</link>
		<comments>http://aleph.llull.net/2009/05/24/optimizaciones-en-el-blog/#comments</comments>
		<pubDate>Sun, 24 May 2009 20:58:28 +0000</pubDate>
		<dc:creator>Eduard</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[optimización]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://aleph.llull.net/?p=705</guid>
		<description><![CDATA[Desde que Xisco me pidió consejo tras probar varias de sus páginas con YSlow tenía pendiente escribir este post. YSlow es un plugin para Firefox que analiza distintos aspectos que pueden afectar al rendimiento de páginas webs y realiza recomendaciones. Todos los aspectos que se tienen en cuenta giran alrededor del tiempo de carga de [...]]]></description>
			<content:encoded><![CDATA[<p>Desde que <a title="Blog personal d’en Xisco Lladó" href="http://zigazaga.net/">Xisco</a> me pidió consejo tras probar varias de sus páginas con <a title=" Yahoo! YSlow for Firefox" href="http://developer.yahoo.com/yslow/">YSlow</a> tenía pendiente escribir este post. YSlow es un plugin para Firefox que analiza distintos aspectos que pueden afectar al rendimiento de páginas webs y realiza recomendaciones. Todos los aspectos que se tienen en cuenta giran alrededor del tiempo de carga de la web. No entran en temas como optimización de base de datos y otros aspectos internos del servidor.</p>
<p>De <a href="http://developer.yahoo.com/performance/rules.html">todas las reglas</a>, las más sencillas de corregir son:</p>
<ul>
<li><a href="http://developer.yahoo.com/performance/rules.html#expires">Add Expires headers</a></li>
<li><a href="http://developer.yahoo.com/performance/rules.html#gzip">Compress components with gzip</a></li>
<li><a href="http://http://developer.yahoo.com/performance/rules.html#etags">Configure entity tags (ETags)</a></li>
</ul>
<p>Otras reglas pueden suponer reescribir parte de la aplicación pero para solventar estas tres basta con añadir algunas líneas al final del <code>.htaccess</code> del directorio raíz de nuestra web. Hay que tener en cuenta que los modulos necesarios deben estar instalados y la configuración del servidor nos debe permitir establecer esta configuración (directiva <a href="http://httpd.apache.org/docs/2.0/en/mod/core.html#allowoverride">AllowOverride</a>)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #adadad; font-style: italic;"># Add Expires Header</span>
&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_expires.c&gt;
<span style="color: #00007f;">ExpiresActive</span> <span style="color: #0000ff;">on</span>
<span style="color: #00007f;">ExpiresByType</span> image/gif <span style="color: #7f007f;">&quot;access plus 1 week&quot;</span>
<span style="color: #00007f;">ExpiresByType</span> image/jpeg <span style="color: #7f007f;">&quot;access plus 1 week&quot;</span>
<span style="color: #00007f;">ExpiresByType</span> image/png <span style="color: #7f007f;">&quot;access plus 1 week&quot;</span>
<span style="color: #00007f;">ExpiresByType</span> text/css <span style="color: #7f007f;">&quot;access plus 1 week&quot;</span>
<span style="color: #00007f;">ExpiresByType</span> application/javascript <span style="color: #7f007f;">&quot;access plus 1 week&quot;</span>
&lt;/<span style="color: #000000; font-weight:bold;">IfModule</span>&gt;
&nbsp;
<span style="color: #adadad; font-style: italic;"># Compress CSS files</span>
&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> mod_deflate.c&gt;
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE text/plain text/html text/xml application/rss+xml application/atom_xml
<span style="color: #00007f;">AddOutputFilterByType</span> DEFLATE text/css application/javascript
&lt;/<span style="color: #000000; font-weight:bold;">IfModule</span>&gt;
&nbsp;
<span style="color: #adadad; font-style: italic;"># ETag only use file time and size, but no inode</span>
<span style="color: #00007f;">FileETag</span> MTime Size</pre></td></tr></table></div>

<p>En las líneas 2 a 9 configuramos que las imágenes, hojas de estilo y javascripts tengan una fecha de expiración de una semana a partir del momento en que se ha visitado la página web. Esto significa que el navegador del usuario usará la copia local (fichero cacheado) durante una semana. Este comportamiento puede suponer un problema si tenemos ficheros de estos tipos que vamos modificando sin cambiarle el nombre (p.e. un banner) ya que los navegadores de algunos de los usuarios mantendran las versiones antiguas.</p>
<p>Desde la 12 a la 15 configuramos la compresión de las páginas HTML, feeds (<code>text/xml</code>, <code>application/rss+xml</code> y <code>application/atom_xml</code>), hojas de estilo y javascripts. De esta forma conseguimos ahorrar tráfico (importante si estamos en un hosting con limitaciones de tráfico)  y que el tiempo de transmisión sea menor.</p>
<p>Finalmente, en la última línea configuramos los ETags generados por el propio servidor Apache para los ficheros estáticos. Por defecto, <a href="http://httpd.apache.org/docs/2.0/en/mod/core.html#fileetag">Apache tiene en cuenta tres aspector para generar el ETag</a>: el inodo, fecha de modificación y tamaño. Pero se recomienda no usar el inodo para generarlo ya que si nuestra web empieza a ser conocida y tenemos que distribuir la carga entre varios servidores, es muy poco probable que un fichero tenga el mismo inodo en todos los servidores de la granja. Entonces, el ETag variaría en funcion del servidor que lo generara por lo que no se sacaría provecho a esta cabecera. Para resolverlo, configuramos el Apache para que genere el ETag sólo considerando la fecha de modificación y el tamaño del fichero.</p>
<p>Con esta simple configuración yo conseguí pasar de una puntuación de <a href="http://aleph.llull.net/wp-content/uploads/aleph-yslow-grade-c.png">74</a> a <a href="http://aleph.llull.net/wp-content/uploads/aleph-yslow-grade-b.png">89</a>.</p>
<p>A medida que pueda escribiré algún post más sobre optimización web y como resolverlo en el caso concreto de un blog que usa WordPress.</p>
]]></content:encoded>
			<wfw:commentRss>http://aleph.llull.net/2009/05/24/optimizaciones-en-el-blog/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

