Optimizando FreeBSD mediante compilaciones
Autor: Julio Merino (aka Slink)
Uno de los principales motivos por los que uso FreeBSD es que puedo compilar y optimizar todo lo que se distribuye en código fuente. Una de las ventajas directas de esto es optimizar las librerias y/o ejecutables para el hardware de la máquina, haciendo que funcionen más deprisa. He escrito este pequeño artículo para explicaros qué podéis hacer para optimizar vuestro sistema. El archivo make.confEl archivo principal para las optimizaciones es el /etc/make.conf. En una instalación nueva este archivo no existe, por lo que tendréis que crearlo. Podéis haceros una idea de todo lo que se puede poner en él hojeando el /etc/defaults/make.conf. Hay que tener en cuenta que éste ultimo archivo no debe modificarse, y todos los cambios que queramos poner deben ir en /etc/make.conf. La función de este archivo es predefinir varias variables que tendrán efecto en las compilaciones que hagamos, sea en un make world o en los ports. Variables globalesVoy a describir aquí algunas de las variables que podéis definir en /etc/make.conf que afectan a todo el sistema de compilación. CPUTYPE determina el tipo de microprocesador que tenemos. En función de lo que pongamos aquí, se aplicaran unos flags de optimización u otros (automáticamente) en la compilación. Podéis ver todos los valores posibles en /etc/defaults/make.conf que dependerán de la versión de vuestro sistema. Para un 4.4-STABLE se soportan estos valores: # Intel x86 architecture: # (AMD CPUs) k7 k6-2 k6 k5 # (Intel CPUs) p4 p3 p2 i686 i586/mmx i586 i486 i386 # Alpha/AXP architecture: ev6 pca56 ev56 ev5 ev45 ev4 Una vez determinemos cual es el correcto, procedemos a añadirlo al /etc/make.conf: CPUTYPE=p2 Las siguientes variables importantes son los flags de compilación de C y C++. Para ello disponemos de dos variables: CFLAGS (que afecta al compilador de C) y CXXFLAGS (que afecta al compilador de C++). Debemos ser cuidadosos con los flags que añadimos a estas variables; hay muchos flags que harán que los programas no funcionen bien, o que el sistema se vuelva muy inestable (os lo digo por experiéncia...). Mi recomendación es que uséis estos valores: CFLAGS=-O2 -pipe CXXFLAGS+=-O3 Como podéis ver, en CFLAGS definimos un nivel de optimización dos y la opción -pipe. Ésta ultima no es realmente un flag de optimización; más que nada hará que las compilaciones sean mucho más rápidas usando pipes en lugar de archivos temporales. CXXFLAGS tiene que añadir el contenido nuevo a ella misma, ya que por defecto se define igual que CFLAGS. En este caso añadimos un nivel de optimización tres. Aquí os muestro un CFLAGS que NO, repito, NO debeis usar ya que produce código inestable (i.e. el sistema se reinicia al usar kldload, nmbd o kdeinit sueltan cores, X4 no funciona, top da valores incorrectos, etc):
CFLAGS=-O2 -pipe -malign-double -ffast-math -fomit-frame-pointer \
-funroll-loops -frerun-loop-opt -fgcse -fcse-follow-jumps \
-fcse-skip-blocks -frerun-cse-after-loop -fschedule-insns2
Si he puesto esto aquí es para que os hagáis una idea de todo lo que podeis usar (consultar el info de gcc). Es posible que si usáis alguno de estos flags ganéis velocidad y no sucedan problemas, pero la combinación que os he mostrado no funciona bien, al menos con gcc 2.95. Variables para el make world y el make kernelComo he dicho, con el /etc/make.conf podéis controlar el make world y la compilación del kernel. Una de las variables a destacar es COPTFLAGS. Esta variable define los flags de optimización para el compilador de C que se usarán al compilar los kernels. Es independiente de CFLAGS. Un buen valor para ella es: COPTFLAGS=-O -pipe Si usáis niveles de optimización mas elevados, es posible que el kernel funcione, pero os arriesgáis a que no vaya bien. Además, la diferencia de velocidad que ganaríais sería mínima, por lo que no vale la pena. Ahora voy a describir unas variables que aceleran la compilación de un make world y de un kernel, aunque no afectan los ejecutables ni librerias. Cada vez que compilamos un kernel necesitamos reconstruir todos los módulos que hay en /modules. Muchas veces esto es innecesario, pero es un proceso muy lento. Podemos evitar esta compilación con las siguientes variables: NO_MODULES=true MODULES_WITH_WORLD=true De este modo los módulos no se compilaran con el kernel pero se compilaran junto al make world. Parece razonable que el kernel se compile varias veces bajo un mismo checkout del sistema, pero como el listado de módulos es siempre fijo, con que los compilemos una vez por checkout, será suficiente. Por otro lado podemos definir la variable siguiente para que no se compilen las profiled libraries. Éstas son ráramente útiles, pero necesitan mucho tiempo de compilación que generalmente podemos evitar: NOPROFILE=true
Para terminar esta sección cabe destacar un flag muy útil que podemos usar cuando ejecutamos el make world. Éste es el -jX (dónde X es un numero). Éste flag nos permite mantener varios procesos de compilación funcionando simultáneamente y en varias CPUs. Aunque no dispongamos de varias CPUs este flag también optimiza el tiempo de compilación ya que normalmente el cuello de botella se forma con el acceso a disco. Mi recomendación es que uséis un flag -j4 que mantiene cuatro compilaciones funcionando en paralelo: /usr/src# make -j4 buildworld Si disponéis de varias CPUs, probar con otros valores y determinar cuál os va mejor. Variables para los portsHay muchos ports que soportan opciones de optimización y que muchas veces pasan desapercibidas ya que normalmente no nos fijamos en el proceso de compilación, y es allí donde se nos dicen. Algunas de ellas son las siguientes: WITH_PNG_MMX=yes OPT_ARCH=i586 Siento no disponer de mas, aunque seguro que las hay. Como véis, la primera habilita el soporte MMX en la libreria png, y la segunda habilita la optimización para Pentium en el paquete mpg123. Algunos otros paquetes se autoconfiguran para usar determinadas optimizaciones, por lo que no deberéis preocuparos. Es recomendable que hechéis una ojeada al Makefile de cada port antes de que lo compiléis para que veáis qué opciones soporta. Por otro lado, algunos paquetes soportan opciones de optimización en el proceso de autoconfiguración, pero que no están soportadas por los ports. Un ejemplo claro es qt23 que tiene soporte optimizado para algunas tarjetas gráficas. Para habilitar este soporte podemos editar el archivo /usr/ports/x11-toolkits/qt23/Makefile y añadimos -accel-mach64 a la línea del CONFIGURE_ARGS. Del mismo modo, algunos ports, como kdelibs2, vienen con las opciones de depuración activadas, que hacen que luego vaya mucho más lento. Estas opciones también pueden desactivarse retocando el Makefile. Si queréis ver las opciones de este estilo que soporta cada port, podéis hacer un make extract del paquete. Luego, entráis en el subdirectorio work/ y allí ejecutáis el ./configure con la opción de ayuda. Por ejemplo: # cd /usr/ports/x11/kdelibs2 # make extract # cd work/kdelibs-2.2 # ./configure --help De la salida de este comando vemos las opciones que pueden interesarnos y que añadiremos al CONFIGURE_ARGS del Makefile como he dicho antes. Hemos de ir con cuidado sobre lo que quitamos o añadimos. Debemos recordar que los ports están programados para instalar una série de archivos predefinidos y que, si en el CONFIGURE_ARGS habilitamos alguna opción que haga que algunos archivos no sean creados, el make install fallará luego. Es el caso de mozilla, en el que si deshabilitamos la compilación del programa de correo, la instalación falla. ConclusiónEspero que con estos trucos veáis una de las ventajas claras de usar FreeBSD, y es que podéis aprovechar mucho mejor vuestro ordenador de lo que os imagináis. Por supuesto, todo lo comentado se puede aplicar a NetBSD uSD, pero será necesario que veáis que variables son soportadas o cuál es su nombre, ya que posiblemente se llamen de un modo distinto. Como nota, en estos dos BSD's el archivo se llama /etc/mk.conf. Venga, ¡a compilar! |