10 de septiembre de 2009

Lo que trae 2.6.31

Este es un resumen de las novedades más importantes de Linux 2.6.31, que acaba de salir hace unos momentos. Resumen: soporte de USB 3.0, un equivalente de FUSE para dispositivos de carácteres, mejora de interactividad del escritorio en escritorios con poca memoria, KMS para ATI Radeon, soporte para "performance counters", un detector de pérdidas de memoria, mejoras de readahead y de btrfs, nuevos drivers...

· Soporte de USB 3: Esta versión añade soporte de USB 3.0, contribuido por Sarah Sharp (Intel), y del hardware que soporta la especificación "eXtensible Host Controller Interface (xHCI) 0.95". Aun no hay hardware xHCI en el mercado, pero estos parches han sido probados en el prototipo de Fresco Logic

· CUSE (dispositivos de caracter en espacio de usuario) y OSS Proxy: CUSE es una extension de FUSE que permite implementar en espacio de usuario dispositivos de caracteres y que ha sido contribuido por Tejun Heo (SUSE).

Puede ser utilizado para muchas cosas, por ejemplo para crear un proxy que envie el audio OSS a través de ALSA o a un sistema de sonido que pueda enviar sonido sobre la red. ALSA tiene una emulación de OSS en el kernel pero desgraciadamente esta emulación está en el kernel y se encuentra detrás de la librería en espacio de usuario que multiplexa el sonido, lo cual significa que si tu tarjeta de sonido no soporta múltiples streams de audio concurrentes (la mayoría de las tarjetas modernas no lo soportan), en un momento dado solamente podrás utilizar ALSA o la emulación OSS, pero no ambas a la vez.

OSS Proxy utiliza CUSE para implementar la interfaz OSS - /dev/dsp, /dev/adsp y /dev/mixer. Desde el punto de vista de las aplicaciones, estos dispositivos son verdaderos dispositivos de carácter, y se comportan exactamente igual, asi que puede utilizarse como un sustituto de la capa de emulación OSS. La aplicación envía audio a esos dispositivos, y el Proxy OSS lo reenviará a un "esclavo". En estos momentos solamente hay un esclavo implementado (pulseaudio)

· Mejora de la interactividad bajo presión de memoria: Las páginas de memoria marcadas como PROT_EXEC son páginas que normalmente pertenecen a programas y librerías que se están ejecutando, asi que debería estar cachearse muy bien para proporcionar buenas experiencias de usuario, porque si no están bien cacheadas, las aplicaciones de escritorio sufrirán largas pausas cuando las rutas de código de la aplicación salten a una parte del código que no está cacheada en memoria y tenga que ser releida desde el disco, que es muy lento. Debido a ciertas mejoras de escalabilidad en la gestión de memoria en los últimos kernels, hay ciertos tipos de carga (comunes) que pueden causar que esas páginas PROT_EXEC sean enviadas a la lista de páginas respaldadas por sistema de archivos (las utilizadas para mapear archivos) que son inactivas y pueden ser borradas de la memoria. El resultado es un entorno de escritorio con poca interactividad: las aplicaciones empiezan a responder mal con demasiada facilidad.

En esta versión, se han aplicacion ciertas heurísticas para que sea mucho más dificil sacar a las páginas de código ejecutable de las listas de páginas activas. El resultado es una experiencia de escritorio mejorada: Benchmarks en escritorios con poca memoria miestran que el tiempo de reloj y las faltas "mayores" de memoria (cuando una aplicación salta a una parte del código que no está mapeada en la memoria) se reducen en un 50%, y los números de pswpin se reducen aproximadamente 1/3, eso significa que la interactividad de los escritorios se dobla en condiciones de presión de memoria. Benchmarks de "flusheado" de memoria en un servidor de archivos muestran que el número de faltas mayores cae de 50 a 3 durante lecturas "calientes" del caché.

· Soporte de Mode Setting para ATI Radeon: En esta versión se añade soporte de Kernel Mode Setting (KMS) para ATI Radeon. El hardware soportado es R1XX,R2XX,R3XX,R4XX,R5XX (hasta la X1950). Se está trabajando para proporcionar soporte para R6XX, R7XX y hardware más moderno (radeon de HD2XXX a HD4XXX).

· Performance counters: El subsistema de Contadores de Rendimiento implementa una abstracción de una serie de registros dedicados a medir el rendimiento que están disponibles en la mayoría de CPUs modernas. Miden el número de eventos como: instrucciones ejecutadas, "cpumisses", errores de predicción en las instrucciones condicionales...sin enlentecer el kernel o las aplicaciones. Estos registros tambien pueden generar una interrupción cuando se pasa de cierto número de eventos - y pueden por tanto utilizarse para analizar el código que se ejecuta en esa CPU. En esta versión, se añade soporte para x86, PPC y soporte parcial para S390 y FRV.

No se espera que los usuarios utilizen ellos mismos la API. En lugar de ello, se ha escrito una poderosa herramienta de análisis: "perf", que está disponible en el directorio tools/perf.

perf soporta varios modos de operacion, como "perf top", que muestra una interfaz semejante a la del comando "top", y que puede restringirse a cualquier conjunto de eventos, procesos o CPU. Existe tambien "perf record", que almacena el registro de un análisis en un archivo, y "perf report", que lee el registro y lo muestra en pantalla, o "perf annotate", que muestra la lista de eventos soportados por el hardware, y "perf stat", que ejecuta un comando y muestra sus estadísticas de rendimiento en la pantalla. Toda la documentación y las páginas man están disponibles en el subdirectorio "Documentation". Algunos ejemplos:

$ ./perf stat -r 3 -- echo -n

Performance counter stats for 'echo -n' (3 runs):

2.337404  task-clock-msecs         #      0.566 CPUs    ( +-   1.704% )
     1  context-switches         #      0.000 M/sec   ( +-   0.000% )
     0  CPU-migrations           #      0.000 M/sec   ( +-   0.000% )
   184  page-faults              #      0.079 M/sec   ( +-   0.000% )
4319963  cycles                   #   1848.188 M/sec   ( +-   1.615% )
5024608  instructions             #      1.163 IPC     ( +-   0.722% )
 73278  cache-references         #     31.350 M/sec   ( +-   1.636% )
  2019  cache-misses             #      0.864 M/sec   ( +-   6.535% )

0.004126139  seconds time elapsed   ( +-  24.603% )


$ perf report -s comm,dso,symbol -C firefox -d /usr/lib64/xulrunner-1.9.1/libxul.so | grep :: | head
2.21%  [.] nsDeque::Push(void*)
1.78%  [.] GraphWalker::DoWalk(nsDeque&)
1.30%  [.] GCGraphBuilder::AddNode(void*, nsCycleCollectionParticipant*)
1.27%  [.] XPCWrappedNative::CallMethod(XPCCallContext&, XPCWrappedNative::CallMode)
1.18%  [.] imgContainer::DrawFrameTo(gfxIImageFrame*, gfxIImageFrame*, nsRect&)
1.13%  [.] nsDeque::PopFront()
1.11%  [.] nsGlobalWindow::RunTimeout(nsTimeout*)
0.97%  [.] nsXPConnect::Traverse(void*, nsCycleCollectionTraversalCallback&)
0.95%  [.] nsJSEventListener::cycleCollection::Traverse(void*, nsCycleCollectionTraversalCallback&)
0.95%  [.] nsCOMPtr_base::~nsCOMPtr_base()

· Soporte de IEE 802.15.4 (Low-Rate Wireless Personal Area Networks): El estándar IEEE 802.15.4 define una red inalámbrica de área personal de corto alcance, bajos ratios de transferencia, bajo consumo de energía y poca complejidad. Ha sido diseñada para organizar redes de sensores, interruptores y otros dispositivos automatizadores. El máximo ratio de transferencia permitido es 250 kb/s y el espacio de operaciones es de alrededor de 10m.

· Soporte de Gcov: Esta versión permite la utilización de Gcov, una herramienta de GCC utilizara para analizar ciertos aspectos del código, con el kernel. Gcov es útil para depurar (¿se ha llegado a este código alguna vez?), mejora de tests (¿como cambio mi test para cubrir estas líneas?), minimizar configuraciones del kernel (¿necesito esta opción si el código asociado no se ejecuta nunca?) y otras cosas.

· Kmemcheck: Kmemcheck es una herramienta de depuración. En concreto, es un comprobador dinámico que detecta y advierte sobre memoria no inicializada. Los programadores de espacio de usuario puede que conozcan el memcheck de Valgrind. La principal diferencia entre kmemcheck y memcheck es que memcheck solamente funciona para programas de espacio de usuario, y kmemcheck solo funciona para el kernel.

Activar kmemcheck en un kernel lo enlentece hasta el punto que la máquina no será usable para cargas comunes, como por ejemplo un escritorio interactivo. kmemcheck tambien hace que el kernel use el doble de memoria de lo normal. Por esta razón, kmemcheck es solamente una opción de depuración.

· Kmemleak: Kmemleak detecta posibles pérdidas de memoria de una manera similar a este recolector de basura, con la diferencia de que los objetos huérfanos no son liberados. En vez de eso, un thread del kernel escanea la memoria cada 10 minutos (por defecto) y muestra cualquier nuevo objeto no referenciado en /sys/kernel/debug/kmemleak y advierte de ello en dmesg. Un método similar es utilizado por la herramienta Valgrind (memcheck --leak-check) para detectar pérdidas de memoria en aplicaciones en espacio de usuario.

· Fsnotify: Fsnotify es un subsistema utilizado para notificaciones del sistema de archivos. Fsnotify por si solo no tiene ninguna API a espacio de usuario, proporciona la base para implementar otros sistemas de notificación como dnotify, inotify y fanotify (este último será incluido en futuras versiones). De hecho, en esta version dnotify e inotify han sido reescritos sobre Fsnotify, eliminando al mismo tiempo el horrible y complejo código que utilizaban esos sistemas. Fsnotify proporciona un mecanismo para que "grupos" se registren para ser notificados de una serie de eventos del sistema de archivos a los que envía dichos eventos, y el bloqueo es mucho más sencillo. Fsnotify tiene otros beneficios, como reducir el tamaño de la estructura que almacena información de un inodo.

· Soporte preliminar para clientes NFS 4.1: 2.6.30 Añadió cierto soporte orientado a desarrolladores de NFS 4.1. Esta versión añade soporte opcional para los borradores de la versión 4.1 en el cliente NFS del kernel.

· Mejoras de readahead: Esta versión incluye un algoritmo de readahead "basado en contexto". El actual algoritmo detecta lecturas entremezcladas de un modo pasivo, el algoritmo nuevo garantiza descubrir la secuencialidad sin importar como estén entremezclados los streams. Los beneficiarios de este algoritmo son las lecturas estrictamente entremezcladas y los procesos con ES cooperativa (por ejemplo, NFS y SCST). Benchmarks de SCST muestran mejoras del 6%~40% en varios casos y consiguen igual rendimiento en otros.

Tambien hay algunas mejoras al readahead de memoria mapeada. En un escritorio NFS-root, el readahead de mmap redujo las faltas mayores de memoria 1/3 sin sobrecargas notables, el IO llevado a cabo por mmap puede reducirse en 1/4.

Esto es todo. Hay otras mejoras, como un driver para dispositivos Intel Wireless Multicomm 3200, mejoras notables de btrfs, IPv4 sobre Firewire...para ver la lista completa, aquí.

2 de septiembre de 2009

¿Grand Central Dispatch, retorno de M:N?

Como es sabido, a grandes rasgos hay dos maneras de implementar threads en los sistemas operativos, 1:1 y M:N, durante años se mantuvo que M:N era lo más apropiado, sin embargo 1:1 acabó ganando la batalla. Solaris, que era uno de los mayores representantes de M:N, hizo que en Solaris 9 cambiara por defecto a 1:1 por la simple razón de que era más rápido y tenía mucho menos código, Linux 2.6 optó tambien por 1:1 en su NTPL. Con el tiempo, NetBSD y FreeBSD, que se resistían, tambien se pasaron a 1:1.

En OS X 10.6 Apple ha implementado una serie de mecanismos con el propósito de facilitar a los programadores la utilización de todos los cores y procesadores de los sistemas modernos. Es muy recomendable leer la parte del análisis de OS X 10.6 de Arstechnica que habla sobre este tema, concretamente de la página 10 a la 14. Esos mecanismos, que son una de las cosas más interesantes que se han hecho en OS X (no faltará quien diga que eso de gestionar threads es viejo y que no tiene nada de interesante, o que me cite a BeOS sin pararse a leer la parte del artículo donde explica claramente por qué lo que ha hecho Apple es mucho más práctico y eficiente que el "pervasive multithreading"). Todo ello se basa en unas extensiones a C y en una especie de gestor de threads llamado "Grand Central Dispatch".

Este "dispatcher" se encarga de mantener unas listas de los "bloques" que las aplicaciones crean gracias a la ya referida extensión de C, y repartirlos entre unos pocos threads creados a tal efecto. Se podría decir que huele un poco a M:N, es decir, un proceso que ofrece su contexto de ejecución a threads que son controlados por una especie de gestor de procesos (Grand Central Dispatch) que funciona en espacio de usuario...¿o no?

En cierto modo, a primera vista hay analogías, pero mirado en detalle no creo que se pueda afirmar que tiene que ver con M:N. Fundamentalmente porque M:N es un diseño para implementar threads, mientras que GCD es un sistema que gestiona bloques. Aunque estos bloques podrían compararse con threads no parece apropiado hacerlo. Pretenden ser más bien una especie de subunidades de trabajo, mientras que los threads son más bien subprocesos (si alguien tiene opinión al respecto sería interesante). Se podría argumentar que un thread puede utilizarse tambien para crear "subunidades de trabajo" en un programa, pero tambien puede no serlo. Un bloque hace su trabajo y desaparece, un thread puede durar tanto como el proceso que lo creo. De ahí que GCD no sea (y quizás ni tenga) en realidad un verdadero "gestor de procesos", porque no reasigna el tiempo de ejecución de un bloque-proceso a otro dependiendo de diferentes variables, como haría M:N, tan solo se limita a asignar un bloque a un thread y esperar a que termine (aun está por ver/documentar como gestiona GCD un bloque que se queda en un loop). Pero todo este tema de GCD es muy nuevo, y habrá que ver como evoluciona con los años, y como lo imitan en otros SOs que reimplementen la idea.

28 de agosto de 2009

Nokia N900

Aunque he tenido tiempo de sobra para actualizar no he querido hacerlo, porque hunde el orgullo de un bloguero publicar cosas que no va a leer el mayor número posible de personas. Además, el resto del mundo tambien ha andado de vacaciones y no ha ocurrido gran cosa que pudiera ser útil para contar aquí.

Ayer sin embargo se anunció una cosa bastante interesante, el Nokia N900. Es un descendiente del N810 y perteneciente a esa línea de productos basados en Maemo que tanto ruido lleva haciendo entre los seguidores del software libre pero que no ha tenido mucho éxito comercial.

Con el N900 la cosa podría cambiar, principalmente porque lo han convertido en lo que siempre se quiso que fuera: un teléfono, que unido a las impresionantes mejoras que han tenido lugar en Maemo 5 lo convierten en...otro imitador del iPhone (incluso su página web es una copia de apple.com), pero en uno decente. E inesperado, porque creo que no había mucha gente que esperara que Maemo se convirtiera en un contendiente relevante en el tema de los sistemas operativos para smartphones. Yo al menos pensaba que acabarían optando por Android sin complicarse la vida, pero el giro que supone Maemo 5 cambia mucho las cosas.

La pena de Maemo es que de haber tenido Nokia un poco más de voluntad, podrían haberlo convertido en lo que Android pretende ser: una plataforma para todo tipo de fabricantes que quieran usar Linux en sus dispositivos. Y en realidad hasta se podría decir que Nokia aun podría intentar lograrlo: Habrá que ver como evolucionan todas las plataformas, pero estando Maemo en manos de una compañía que tambien diseña el hardware y con notorias ganas de invertir para conservar su liderazgo, y siendo Maemo una plataforma más "nativa" (nada de Java ni de Javascript, a diferencia de Android y de Palm) y por tanto más amigable para los desarrolladores de software libre, todo se andará.