{"id":472,"date":"2026-03-08T20:22:09","date_gmt":"2026-03-08T20:22:09","guid":{"rendered":"https:\/\/hackcuba.net\/?p=472"},"modified":"2026-03-08T20:22:09","modified_gmt":"2026-03-08T20:22:09","slug":"optimizando-codigo-con-gcc","status":"publish","type":"post","link":"https:\/\/hackcuba.net\/?p=472","title":{"rendered":"Optimizando c\u00f3digo con GCC"},"content":{"rendered":"\n<p>Primeramente un saludo a los creadores de BlackHat y como siempre a los lectores ya establecidos, as\u00ed como los nuevos que se suman a esta positiva iniciativa, pues sobre todo porque potencia el acceso a la libre informaci\u00f3n de la que \u00abmuchos\u00bb no disponen a diario, ni siquiera muy a menudo en nuestra Cuba de hoy.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Entre tantos temas posibles sobre los cual redactar en este inmenso mundo de <em>software<\/em> e implementaciones de GNU\/Linux, pens\u00e9 en varias cosas, sin embargo, la primera por la que me decid\u00ed fue por escribir el presente art\u00edculo y documentar algo no tan conocido por los usuarios novatos\/intermedios de GNU\/Linux. Me refiero a la optimizaci\u00f3n de programas a trav\u00e9s de la compilaci\u00f3n de los mismos con modificaciones en los \u00abflags\u00bb del compilador GCC.<\/p>\n\n\n\n<p>Algunos se preguntar\u00e1n de qu\u00e9 me sirve y en realidad qu\u00e9 puedo ganar con ello; para dejarlo bien claro todo esto se resume as\u00ed:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Cuando compilamos un programa tenemos la oportunidad de optimizarlo.<\/li>\n\n\n\n<li>Optimizarlo para que se ajuste a las instrucciones (SSE1, SSE2, SSE3, por poner un ejemplo) presentes en un determinado procesador (ej: Pentium4).<\/li>\n\n\n\n<li>Lograr que el binario (ejecutable nativo de la plataforma) tenga un <em>size<\/em> \u00abmucho\u00bb m\u00e1s reducido, menos consumo de memoria y mayor velocidad.<\/li>\n<\/ol>\n\n\n\n<p>Con estos principios sobre la mesa vamos a repasar c\u00f3mo podemos optimizar el <em>software<\/em> en nuestra distribuci\u00f3n GNU\/Linux preferida.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">[ <em>Flags<\/em> del compilador ]<\/h2>\n\n\n\n<p>Vi\u00e9ndolo de una manera sencilla, los <em>flags<\/em> son opciones que se le pasan al compilador a modo de par\u00e1metros, las cuales \u00e9l reconoce y toma acciones sobre ella. Lo importante es que al usar los <em>flags<\/em> de GCC tenemos muchas posibilidades de optimizar, por ejemplo, para uso diario normal o uso diario para desarrollo. Para ello se deben ajustar los <em>flags<\/em> y generar un binario con s\u00edmbolos de <em>debugging<\/em>; esto \u00faltimo por citar un caso.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">[ <em>Flags<\/em> por defecto ]<\/h2>\n\n\n\n<p>La mayor\u00eda de los programas y bibliotecas son compiladas por defecto en nivel de optimizaci\u00f3n 2 (un nivel normal) con las opciones <code>-g -O2<\/code> del GCC. Hay que tener bien claro que la compilaci\u00f3n de programas para Linux se basa en la GNU\/ToolChain, uni\u00f3n de gcc\/make\/autoconf\/libtool\/automake y algunos m\u00e1s, por lo cual el 100% de los programas com\u00fan y corrientes al menos incluyen un fichero Makefile (no siempre, pero generalmente el Makefile es generado despu\u00e9s del proceso llevado a cabo a trav\u00e9s del <em>script <\/em><em>configure<\/em>, para que despu\u00e9s el Makefile suela incluir los <em>flags<\/em> del compilador detectados por defecto, entre otras cosas). En este caso las pruebas las voy a hacer con el c\u00f3digo fuente del reproductor Alsaplayer, versi\u00f3n 0.99.78.<\/p>\n\n\n\n<p>Para comprobar lo antes dicho, he descomprimido el <em>file<\/em> con el c\u00f3digo y, tras hacer un <code>cd<\/code> al <em>dir<\/em>, compruebo de hecho que el Makefile no existe. Esto ocurre primeramente porque Alsaplayer basa su construcci\u00f3n en una conformaci\u00f3n cl\u00e1sica de las herramientas GNU que siguen los siguientes pasos:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Configurar el \u00e1rbol de las fuentes (<em>configure<\/em>)<\/li>\n\n\n\n<li>Crear un Makefile (sobre todo con los datos provenientes de <em>makefile.in<\/em> y <em>makefile.am<\/em>), con los <em>flags<\/em> detectados del compilador, linkeador, bibliotecas, etc.<\/li>\n\n\n\n<li>El Makefile generado tendr\u00e1 una serie de reglas que le indicar\u00e1n al compilador qu\u00e9 nivel de optimizaci\u00f3n tendr\u00e1 el binario o bibliotecas (por defecto recuerden que es 02 en casi todos los paquetes de c\u00f3digo fuente), contra qu\u00e9 bibliotecas se van a enlazar, los par\u00e1metros del enlazador (LD), reglas de limpieza del \u00e1rbol, entre muchas otras incluyendo \u00absiempre\u00bb los <em>flags<\/em> del compilador.<\/li>\n\n\n\n<li>Crear todo el c\u00f3digo objeto y enlazarlo con \u00abmake\u00bb (en realidad el enlazado lo realiza el GNU LD, uno de los linkeadores m\u00e1s efectivos en la actualidad.<\/li>\n<\/ol>\n\n\n\n<p>Esto es una mirada muy b\u00e1sica al proceso; en realidad es mucho m\u00e1s complejo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">[ CFLAGS y CXXFLAGS ]<\/h2>\n\n\n\n<p>Estos <em>flags<\/em> son claves. A trav\u00e9s de ellos vamos a indicarle al compilador para qu\u00e9 procesador y el nivel de optimizaci\u00f3n con que deben ser compilados los <em>sources<\/em>.<\/p>\n\n\n\n<p><strong>CFLAGS<\/strong>:<br>Como lo indica, son los <em>flags<\/em> para el compilador de c\u00f3digos fuente en lenguaje C.<\/p>\n\n\n\n<p><strong>CXXFLAGS:<\/strong><br>Lo mismo, para C++.<\/p>\n\n\n\n<p>Hay varias maneras de establecer los <em>flags<\/em> de GCC; sin embargo, la m\u00e1s sencilla y \u00fatil de todas es a trav\u00e9s de variables de entorno, ya que <em>configure<\/em> las lee si estuvieran establecidas y agrega su valor a la variable <code>CFLAGS<\/code> en el Makefile final. Otra manera es editar el Makefile generado a mano y modificar las entradas <code>CFLAGS<\/code> y <code>CXXFLAGS<\/code>.<\/p>\n\n\n\n<p>Dicho esto y como banco de pruebas, primeramente voy a configurar Alsaplayer sin <em>flags<\/em> para que detecte solamente lo que est\u00e9 establecido por defecto. Corro <em>configure<\/em> de la siguiente manera:<\/p>\n\n\n\n<p><code>.\/configure --prefix=\/opt\/alsaplayer-test<\/code><\/p>\n\n\n\n<p>La salida m\u00e1s importante que nos interesa es la siguiente:<\/p>\n\n\n\n<p><code>\"checking for gcc optimization flags... -O2 -fexpensive-optimizations<br>-funroll-loops -finline-functions -ffast-math -Wall\"<\/code><\/p>\n\n\n\n<p>En ese momento se chequearon los <em>flags<\/em> de optimizaci\u00f3n de GCC, pues como mencionaba anteriormente casi el 100% de los paquetes se ajustan para la optimizaci\u00f3n en nivel 2, que es la com\u00fan (todas las distribuciones de Linux basadas en i386 tienen este nivel de optimizaci\u00f3n para poder correr lo mismo en un 486 que en un Pentium4). Estos <em>flags<\/em> tambi\u00e9n se ven afectados por algunos par\u00e1metros definidos dentro del propio sistema de construcci\u00f3n de Alsaplayer, por ejemplo <code>-funroll-loop<\/code> (desenrollado de bucles) o <code>-Wall<\/code> (muestra todos los <em>warnings<\/em> o advertencias en el momento de la compilaci\u00f3n).<\/p>\n\n\n\n<p>Despu\u00e9s finalizado el <em>configure<\/em>, un detalle importante es que se ha creado el Makefile que GNU make usar\u00e1 para llamar al compilador, enlazador y algunas utilidades necesarias; el detalle es que en la cabecera del nuevo Makefile se encuentra una l\u00ednea como \u00e9sta:<\/p>\n\n\n\n<p><code># Makefile. Generated from Makefile.in by configure.<\/code><\/p>\n\n\n\n<p>Esto no lleva mucha explicaci\u00f3n, porque ya lo he mencionado: se ha creado Makefile desde el Makefile.in y el trabajo lo ha hecho el <em>script<\/em> <em>shell configure<\/em>.<\/p>\n\n\n\n<p>Si vemos ahora el contenido de Makefile, podemos hacer una b\u00fasqueda de los <em>flags<\/em> del compilador que se han escrito en \u00e9l. Exactamente las cadenas en cuesti\u00f3n son:<\/p>\n\n\n\n<p><code>CFLAGS = -g -O2<br>CXXFLAGS = -g -O2<\/code><\/p>\n\n\n\n<p>Aqu\u00ed hay definido un nivel de optimizaci\u00f3n por <em>default<\/em>.<\/p>\n\n\n\n<p>Seguido, ejecuto un <em>make<\/em> y <em>make install<\/em> para compilar y, finalmente, para instalar Alsaplayer en mi sistema y comprobar con estas optimizaciones qu\u00e9 <em>size<\/em> tiene el binario final, durante la compilaci\u00f3n vemos l\u00edneas como \u00e9stas (se nota el uso de los <em>flags<\/em> inmediatamente):<\/p>\n\n\n\n<p><code>\"-Wall -g -O2 -D_REENTRANT -DADDON_DIR=\\\"\/opt\/alsaplayer-test\/lib\/alsaplayer\\\" -g -O2<br>-MT support.lo -MD -MP -MF .deps\/support.Tpo -c -o support.lo support.cpp\"<\/code><\/p>\n\n\n\n<p>Una vez finalizado, la salida de un:<\/p>\n\n\n\n<p><code>ls -lh \/opt\/alsaplayer-test\/bin\/alsaplayer | awk '{ print $5 }'<\/code><\/p>\n\n\n\n<p>Luce as\u00ed:<\/p>\n\n\n\n<p><code>\"791K\"<\/code><\/p>\n\n\n\n<p>Un <em>size<\/em> que no me gusta para nada, trat\u00e1ndose de un <em>software<\/em> tan peque\u00f1o. Dicho esto, vamos a ver c\u00f3mo ajustamos los <em>flags<\/em> para generar un binario m\u00e1s reducido.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">[ Estableciendo los <em>flags<\/em> ]<\/h2>\n\n\n\n<p>Lo primero es establecer la variable <code>CFLAGS<\/code>. Vamos all\u00e1 y en este ejemplo voy a optimizar la generaci\u00f3n de c\u00f3digo para Pentium4.<\/p>\n\n\n\n<p><code>export CFLAGS=\"-s -O3 -march=pentium4\"<\/code><\/p>\n\n\n\n<p>Aqu\u00ed el nivel de optimizaci\u00f3n es el m\u00e1s alto (O3); n\u00f3tese que no es CERO, sino la letra \u00abO\u00bb. Otro detalle es que optimizamos para Pentium4 y generamos c\u00f3digo dependiente del procesador.<\/p>\n\n\n\n<p>De por s\u00ed esto solamente no basta, vamos a setear <code>CXXFLAGS<\/code> as\u00ed:<\/p>\n\n\n\n<p><code>export CXXFLAGS=$CFLAGS<\/code><\/p>\n\n\n\n<p>Esto quiere decir que <code>CXXFLAGS<\/code> va a ser igual al valor actual de la variable de entorno, ya establecida <code>CFLAGS<\/code>, o sea, las mismas optimizaciones. Vamos a comprobar en el <em>shell<\/em>:<\/p>\n\n\n\n<p><code>echo $CFLAGS<br>echo $CXXFLAGS<\/code><\/p>\n\n\n\n<p>La salida debe ser id\u00e9ntica en los dos casos, ya que <code>CXXFLAGS<\/code> posee el mismo valor que <code>CFLAGS<\/code>. Hasta aqu\u00ed ya estamos listos, para mi ejemplo voy a volver a compilar Alsaplayer con estas variables ya establecidas y a repasar el proceso a ver qu\u00e9 sucede. Para ello limpio el \u00e1rbol de las fuentes de Alsaplyer con <code>make distclean<\/code>. Esto borra todos los c\u00f3digos objeto, binarios, bibliotecas y elimina el Makefile generado, o sea, crea el entorno desde cero, limpio.<\/p>\n\n\n\n<p>Corro el mismo <em>configure <\/em>de hace un momento:<\/p>\n\n\n\n<p><code>.\/configure --prefix=\/opt\/alsaplayer-test-optimizado<\/code><\/p>\n\n\n\n<p>Aqu\u00ed lo diferente es que lo instalo en otro lugar para despu\u00e9s poder ver la diferencia entre el anterior. Terminado el <em>configure<\/em> paso a analizar el contenido del Makefile generado. La variable <code>CFLAGS<\/code> luce as\u00ed:<\/p>\n\n\n\n<p><code>CFLAGS = -s -O3 -march=pentium4<\/code><\/p>\n\n\n\n<p>y <code>CXXFLAGS<\/code> as\u00ed:<\/p>\n\n\n\n<p><code>CXXFLAGS = -s -O3 -march=pentium4<\/code><\/p>\n\n\n\n<p>Si comparamos con la anterior podemos ver la diferencia, vuelvo a hacer <em>make<\/em> y <em>make install<\/em> y observo esta l\u00ednea, por ejemplo:<\/p>\n\n\n\n<p><code>\" -s -O3 -march=pentium4 -D_REENTRANT -DADDON_DIR=\\\"\/opt\/alsaplayer-test\/lib\/alsaplayer\\\"\"<\/code><\/p>\n\n\n\n<p>Donde de hecho, ya se est\u00e1n aplicando los <em>flags<\/em>.<\/p>\n\n\n\n<p>El momento ha llegado y la salida de un:<\/p>\n\n\n\n<p><code>ls -lh \/opt\/alsaplayer-test-optimizado\/bin\/alsaplayer | awk '{ print $5 }'<\/code><\/p>\n\n\n\n<p>Luce as\u00ed:<\/p>\n\n\n\n<p><code>\"163K\"<\/code><\/p>\n\n\n\n<p>Es, evidente la gran optimizaci\u00f3n que se ha producido, desde 791 Kb hasta 163 Kb.<\/p>\n\n\n\n<p>Como ven son muchas las ventajas, pero no todo es as\u00ed de sencillo; existen aplicaciones que no compilar\u00e1n bajo estos <em>flags<\/em> de optimizaci\u00f3n, ya que sencillamente no est\u00e1n hechas para ellos. Lo que s\u00ed me provoca alegr\u00eda es saber que mientras la versi\u00f3n precompilada de Apache2 me ocupa 1 Mb, el ejecutable del servidor, compil\u00e1ndolo de esta forma me ocupa s\u00f3lo 200 Kb y encima me funciona igual de bien o mejor, sin el m\u00e1s m\u00ednimo problema.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Referencia de los parametros al compilador::<\/h2>\n\n\n\n<p><code>-s<\/code> Es una opci\u00f3n del enlazador que quita todas las tablas de s\u00edmbolos del ejecutable, entre otras cosas.<\/p>\n\n\n\n<p><code>O3<\/code> Optimizar al m\u00e1s alto nivel, se genera c\u00f3digo espec\u00edfico de la m\u00e1quina.<\/p>\n\n\n\n<p><code>O2<\/code>Nivel de optimizaci\u00f3n por defecto.<\/p>\n\n\n\n<p>Lista de par\u00e1metros para <code>-march<\/code>:<\/p>\n\n\n\n<p><code>i386<\/code> Intel 386<br><code>i486<\/code>&nbsp;Intel\/AMD 486<br><code>pentium<\/code>&nbsp;Intel Pentium<br><code>pentiumpro<\/code>&nbsp;Intel Pentium Pro<br><code>pentium2<\/code>&nbsp;Intel PentiumII\/Celeron<br><code>pentium3<\/code>&nbsp;Intel PentiumIII\/Celeron<br><code>pentium4<\/code>&nbsp;Intel Pentium 4\/Celeron<br><code>k6<\/code>&nbsp;AMD K6<br><code>k6-2<\/code>&nbsp;AMD K6-2<br><code>K6-3<\/code>&nbsp;AMD K6-3<br><code>athlon<\/code>&nbsp;AMD Athlon\/Duron<br><code>athlon-tbird<\/code>&nbsp;AMD Athlon Thunderbird<br><code>athlon-4<\/code>&nbsp;AMD Athlon Version 4<br><code>athlon-xp<\/code>&nbsp;AMD Athlon XP<br><code>athlon-mp<\/code>&nbsp;AMD Athlon MP<br><code>winchip-c6<\/code>&nbsp;Winchip C6<br><code>winchip2<\/code>&nbsp;Winchip 2<br><code>c3<\/code>&nbsp;VIA C3 Cyrix<\/p>\n\n\n\n<p>Cada una de ellas son espec\u00edficas a ese procesador, por ejemplo, si s\u00f3lo se va a correr <em>software<\/em> sobre su m\u00e1quina, es recomendado aplicarlas; sin embargo, si transporta <em>software<\/em>, digamos desde un P3 a un P4, no se deber\u00edan hacer optimizaciones, ya que el binario no funcionar\u00eda.<\/p>\n\n\n\n<p>Espero que este art\u00edculo les sirva de mucho para optimizar su <em>software<\/em> a la medida de su PC. Un saludo.<\/p>\n\n\n\n<p>Por el momento esto es todo, <em>and&#8230; BlackHat for all&#8230; happy day<\/em>.<\/p>\n\n\n\n<p>Escrito por Orestes Leal R. [<a href=\"mailto:orestesleal13022@cha.jovenclub.cu\">orestesleal13022@cha.jovenclub.cu<\/a>]<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Primeramente un saludo a los creadores de BlackHat y como siempre a los lectores ya establecidos, as\u00ed como<\/p>\n","protected":false},"author":2,"featured_media":473,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,36],"tags":[148,58,38],"class_list":["post-472","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programacion","category-proyecto-blackhat","tag-gcc","tag-programacion","tag-proyecto-blackhat"],"_links":{"self":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts\/472","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=472"}],"version-history":[{"count":1,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts\/472\/revisions"}],"predecessor-version":[{"id":474,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/posts\/472\/revisions\/474"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=\/wp\/v2\/media\/473"}],"wp:attachment":[{"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=472"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=472"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackcuba.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=472"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}