<?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>Codigo Manso &#187; error comun</title>
	<atom:link href="http://www.codigomanso.com/es/tag/error-comun/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.codigomanso.com</link>
	<description>Programación, informática y tecnología</description>
	<lastBuildDate>Sun, 21 Aug 2011 10:54:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Un error común en programación: Lenguajes compilados</title>
		<link>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion-lenguajes-compilados/</link>
		<comments>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion-lenguajes-compilados/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 18:41:59 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[cl]]></category>
		<category><![CDATA[compilador]]></category>
		<category><![CDATA[error comun]]></category>
		<category><![CDATA[g++]]></category>
		<category><![CDATA[interprete]]></category>
		<category><![CDATA[optimizar]]></category>
		<category><![CDATA[Programacion]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/?p=167</guid>
		<description><![CDATA[Juanjo ha apuntado que muy probablemente esto que yo comentaba como un típico error que la gente comete cuando programa, se optimiza en los lenguajes compilados (vease C/C++/Java/&#8230;).
Lo que proponía Juanjo (de probarlo con el g++ optimizando a tope) me ha parecido buena idea, así que he hecho unas cuantas pruebas en C++. 
Los resultados [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://blackshell.usebox.net/" target="_blank">Juanjo</a> ha apuntado que muy probablemente esto que yo comentaba como un <a href="http://www.codigomanso.com/2008/11/un-error-comun-en-programacion/" target="_blank">típico error que la gente comete cuando programa</a>, se optimiza en los lenguajes compilados (vease C/C++/Java/&#8230;).</p>
<p style="text-align: justify;">Lo que proponía Juanjo (de probarlo con el g++ optimizando a tope) me ha parecido buena idea, así que he hecho unas cuantas pruebas en C++. </p>
<p>Los resultados han sido interesantes <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p style="text-align: justify;">Para mi grata sorpresa, el g++ ha optimizado muy bien la función <strong>strlen</strong>. Sin embargo, no es capaz de optimizar &#8220;cualquier&#8221; función que tenga sus mismas características.</p>
<p style="text-align: justify;">En el archivo <strong>test-strlen.cpp</strong> he realizado varias pruebas (más abajo están los fuentes descargables en un .tgz).</p>
<p style="text-align: justify;">La primera prueba ha sido realizar un bucle con <strong>strlen</strong>, tal cual el código de PHP, y otro donde el <strong>strlen</strong> está fuera del bucle.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #666666; font-style: italic;">// strlen dentro del bucle</span>
 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;=</span> strlen <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    copy <span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> str<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
 <span style="color: #808080; font-style: italic;">/* [...] */</span>
&nbsp;
 <span style="color: #666666; font-style: italic;">// strlen fuera del bucle</span>
 len <span style="color: #339933;">=</span> strlen <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;=</span> len<span style="color: #339933;">;</span> j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    copy <span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> str<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></div></div>

<p style="text-align: justify;">Ha resultado que el g++ ha optimizado muy bien el primer bucle, hasta el punto que ambos probablemente ejecuten el mismo código, no se aprecia diferencia.</p>
<p style="text-align: justify;">Una vez hecho esto, me he dicho, voy a fastidiar un poco al compilador, así que he añadido una linea, que básicamente modifica <strong>str</strong>, que es la cadena que se le pasa al <strong>strlen</strong>, para que el compilador tenga que evaluar siempre el bucle:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #666666; font-style: italic;">// strlen dentro del bucle, modificando str</span>
 <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> j <span style="color: #339933;">&lt;=</span> strlen <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    copy <span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> str<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>j <span style="color: #339933;">==</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> str<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> str<span style="color: #009900;">&#91;</span>j<span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></div></div>

<p style="text-align: justify;">El caso es que ha funcionado, básicamente el compilador no lo ha podido optimizar, no obstante esto no me vale para ejemplificar lo que decía en el artículo anterior, porque el compilador ha hecho lo que tenía que hacer, y la variable ha sido modificada dentro.</p>
<p style="text-align: justify;">He aquí los resultados de <strong>test-strlen</strong>:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Making the common mistake(not optimizable): 9.20
Making the common mistake(optimizable by the compiler): 0.00
Avoiding the common mistake: 0.00</pre></div></div>

<p style="text-align: justify;">Total, que he creado otro archivo de ejemplo, el <strong>test-custom-strlen.cpp</strong> cuyo objetivo es implementar una función equivalente a strlen y ver si el compilador es igual de inteligente.</p>
<p style="text-align: justify;">Básicamente, en este archivo he creado 5 funciones, vease: <strong>custom_strlen, custom_strlen_const, custom_strlen_const2, strlen_wrap, strlen_wrap_const</strong></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/** this is a custom strlen function */</span>
size_t custom_strlen <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>ptr <span style="color: #339933;">=</span> str<span style="color: #339933;">;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ptr <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>ptr <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #009900;">&#41;</span> ptr<span style="color: #339933;">++;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>size_t<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>ptr <span style="color: #339933;">-</span> str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/** this is same as above, but telling the compiler we are not touching str*/</span>
size_t custom_strlen_const <span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>ptr <span style="color: #339933;">=</span> str<span style="color: #339933;">;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ptr <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>ptr <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #009900;">&#41;</span> ptr<span style="color: #339933;">++;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>size_t<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>ptr <span style="color: #339933;">-</span> str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/** this strlen updates input string, no matter that is const */</span>
size_t custom_strlen_const2 <span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>ptr <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>str<span style="color: #339933;">;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ptr <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>ptr <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #009900;">&#41;</span> ptr<span style="color: #339933;">++;</span>
&nbsp;
  <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>str<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'a'</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// update string</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>size_t<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>ptr <span style="color: #339933;">-</span> str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/** this is a wrapper over strlen function */</span>
size_t strlen_wrap <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> strlen <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/** this is a wrapper over strlen function with constant input */</span>
size_t strlen_wrap_const <span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> strlen <span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p style="text-align: justify;">Y los resultados ha sido los siguientes:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">using custom_strlen: 3.90
using custom_strlen_const: 4.05
using custom_strlen_const2: 4.04
using strlen_wrap: 0.00
using strlen_wrap_const: 0.00</pre></div></div>

<p style="text-align: justify;">Vamos, que el compilador, con -O3, no ha sido capaz de optimizar ninguna de mis funciones. Y el caso es que la función <strong>custom_strlen_const</strong> era candidata para ser optimizada igual que el strlen (función con un parámetro constante, internamente usa const para todo y no cambia el valor de nada).</p>
<p style="text-align: justify;">Total, que sigo manteniendo la misma opinión que en el artículo anterior: <strong>si una función se va a evaluar siempre a lo mismo, mejor que esté fuera del bucle, porque no se sabe si el compilador o intérprete va a ser capaz de optimizarla o no.</strong></p>
<p style="text-align: justify;">También me gustaría decir que por lo general este tipo de cosas, normalmente, tampoco va a suponer ningún cuello de botella en ninguna aplicación, ni va a suponer tiempos abismales de ejecución, por lo que no es preciso prestarle mucha importancia; ahora bien, son pequeños detalles, que se van sumando y sumando, y oye, quizá no reduzcan los tiempos un 30%, pero un 5%&#8230; <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: justify;"><a href="http://www.codigomanso.com/archives/misc/test-gcc-strlen.tgz" target="_blank">Aquí teneis el archivo comprimido con los códigos fuentes de ejemplo</a>. (descomprimir, ejecutar make y listo)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion-lenguajes-compilados/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Un error común en programación</title>
		<link>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion/</link>
		<comments>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 09:28:16 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[bucles]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[error comun]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/?p=156</guid>
		<description><![CDATA[Un error que comete mucha gente, aunque mucha no se da cuenta, y la mayoría de veces pasa desapercibido, se da a la hora de poner las condiciones en los bucles. Se debe tener cuidado cuando se hacen llamadas dentro de un bucle, porque algo que a priori puede parecer O(n) se convierte en O(n2).
¿Alguien [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Un error que comete mucha gente, aunque mucha no se da cuenta, y la mayoría de veces pasa desapercibido, se da a la hora de poner las condiciones en los bucles. Se debe tener cuidado cuando se hacen llamadas dentro de un bucle, porque algo que a priori puede parecer O(n) se convierte en O(n<sup>2</sup>).</p>
<p style="text-align: justify;">¿Alguien ve algo raro en el siguiente código?</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #990000;">strlen</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$string</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// whatever this loop does</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p style="text-align: justify;">A priori ¿Parece que todo está bien, no? Si te lo parece es que no eres consciente aún.</p>
<p style="text-align: justify;">Es bien sabido que las condiciones de los bucles se evaluan tantas veces como iteraciones tiene el bucle, con esto no estoy descubriendo nada a nadie, sin embargo, si se mete un <strong>strlen</strong> para medir la longitud de la cadena en un bucle que se ejecuta tantas veces como caracteres hay, acabamos de elevar al cuadrado el tiempo de ejecución.</p>
<p style="text-align: justify;">Tanto en C como en PHP, la función <strong>strlen</strong> necesita recorrer toda la cadena hasta encontrar el &#8216;\0&#8242; para determinar su longitud, así pues, si la longitud es 20, strlen necesitará 20 iteraciones para determinar que la longitud es 20. El problema es que el bucle que estamos haciendo también tiene 20 iteraciones, y en cada iteración se ejecuta strlen, que consume otras 20 iteraciones (claro que en PHP esas 20 iteraciones se ejecutan en código máquina, y no en el interprete), por lo que tendríamos que el coste de ese bucle para una cadena de 20 caracteres es de 20*(20 + lo que hay dentro del bucle) = 400 + 20*lo que hay dentro del bucle.</p>
<p style="text-align: justify;">El siguiente script (<a href="http://www.codigomanso.com/archives/phpscripts/common_mistake_with_loops_using_strlen.php.txt" target="_blank">error común con los bucles</a>) muestra un ejemplo de esto en PHP, donde dentro del bucle no se hace nada, y se puede observar como un bucle es mucho más lento que el otro.</p>
<p style="text-align: justify;">Los resultados tras ejecutarlo en mi ordenador han sido:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">strlen($sentence) =  12608 bytes
Making the common mistake: 3.02566313744 seconds
Fixing the common mistake: 0.958508968353 seconds</pre></div></div>

<p style="text-align: justify;">Creo que se puede apreciar claramente la diferencia <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: justify;">Finalmente, aunque he usado PHP para ilustrar el error, y concretamente <strong>strlen</strong>, si nos olvidamos de strlen y de PHP, esto es aplicable a otros muchos lenguages C/C++/Java/Pascal/PHP/Python/Perl/Ruby y un largo etcetera; y pasa en todos los lenguajes porque todos los lenguajes usan el mismo concepto, la condicion de salida del bucle se evalua en cada iteración. Quizás no ocurra cuando se utilizan cadenas, porque guardan la longitud en una variable, pero puede que pase al mirar la longitud de listas enlazadas, etc&#8230;</p>
<p style="text-align:justify;"><strong>Conclusión:</strong> si en el bucle estás llamando a una función que siempre te va a devolver lo mismo, mejor guardalo en una variable y usa esa variable dentro del bucle, te ahorrará sorpresas</p>
<p style="text-align:justify;">
<p><strong>Enlaces interesantes:</strong></p>
<ul>
<li><a href="http://www.joelonsoftware.com/articles/fog0000000319.html" target="_blank">Back to basics</a>, un excelente artículo de Joel (<a href="http://local.joelonsoftware.com/mediawiki/index.php/De_vuelta_a_lo_b%C3%A1sico" target="_blank">disponible en Español</a>) donde reflexiona sobre algunas cosas directamente relacionadas con esto.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
	</channel>
</rss>

