next up previous
Siguiente: Lecciones aprendidas Superior: Mejorando NFS Anterior: Cambios que hemos hecho

Subsecciones

Detalles de implementación

Como ya se ha dicho antes, utilizamos un kernel de Linux versión 2.2.12 y un servidor de NFS de espacio de usuario 2.2beta37. No utilizamos el servidor de espacio de kernel porque todavía estaba en estado experimental y tenía todavía algunos errores.

Cambios en el cliente

En el kernel del cliente tuvimos que modificar la llamada al sistema sendfile para que llamase a la operación de copy que añadimos a la estructura de operaciones sobre ficheros. En el caso de un fichero de NFS, este puntero a función apunta a una función llamada nfs_file_copy. Esta función, prepara los parámetros, recoge el puntero de fichero y llama a nfs_file_copy que se ocupa de construir y llamar a la RPC copy, manejando los posibles errores.

Utilizamos la operación de sendfile porque tenía exactamente el interfaz que necesitábamos. Sin embargo, sendfile fue creada, como ya hemos explicado antes, con servidores web y sockets en mente. Puede suceder, pues, que haya algún detalle de sendfile que no hayamos visto que se encuentre específicamente preparado para funcionar bien en el contexto en el que fue diseñada aunque por ahora, no nos hemos encontrado con ningún problema.

Una parte del kernel que fue especialmente ardua de modificar fueron los encapsulados en XDR de los argumentos. El kernel, con el fin de aumentar la eficiencia de estas traducciones, no utiliza un compilador y hay que hacer estas traducciones a mano. Esta es una tarea difícil, tanto para depurar el código, como por lo fácil que es cometer un error.

Otro cambio interesante que realizamos en el kernel cliente es el añadir soporte para una entrada en el sistema de ficheros de /proc. Esta entrada nos permite cambiar y leer variables en tiempo de ejecución del kernel, pudiendo hacer cosas como habilitar o deshabilitar la llamada a copy. Esta entrada en /proc nos resultó absolutamente fundamental a la hora tanto de depurar como de hacer medidas.

Cambios en el servidor

En el servidor sólo tuvimos que modificar nfsd, el demonio de espacio de usuario que hace de servidor de NFS.

Lo único que tuvimos que hacer es añadir la operación copy al programa RPC del servidor. Como el servidor utilizaba para generar las rutinas de traducción de XDR y los stubs en C el compilador rpcgen, esto fue tarea fácil. El procedimiento que seguimos, fue modificar la descripción del programa en XDR, compilarlo con rpcgen y escribir la implementación de la rutina copy. Esta rutina, lo único que tenía que hacer era llamar a read y write localmente, haciendo uso del sistema de ficheros.


El problema de los bloqueos

La aproximación que hemos descrito hasta ahora, tenía ciertos fallos, que tuvimos que arreglar para que el sistema realmente funcionase. El fallo principal y más difícil de encontrar fueron los interbloqueos que generaba la existencia de un único hilo en el servidor de NFS. Como ya se ha comentado, debido a la existencia de este único hilo, si el write era una petición hecha mediante una RPC al mismo servidor de NFS que estaba atendiendo la de copy, se generaba un bloqueo del hilo de ejecución consigo mismo. Este fallo fue bastante difícil de encontrar porque era un error de diseño y apareció en la fase de depuración.

La solución de este problema, que tampoco es tan complicada una vez se ha conseguido localizar, pasa por el dibujo de todos los diagramas de espera que generan las posibles topologías durante la ejecución de una llamada a copy, como se puede ver en la figura 3.

Figura 3: Diagramas de espera para uno dos y tres ordenadores.
\begin{figure}
\begin{center}
\epsfig {file=WFG.eps,width=8cm} \end{center} \end{figure}

Tras ver la figura queda claro que sólo hay dos casos que nos lleven a bloqueo. Ocurre un bloqueo siempre que el origen y el destino estén en la misma máquina. Aunque uno de estos casos (aquel en el que la misma máquina que exporta los ficheros por NFS es la que los monta y es también la que origina el copy) pueda parecer extraño, fue el primero que probamos al hacer el desarrollo en una sola máquina. El segundo (el caso con dos ordenadores y los ficheros origen y destino en el que no es originario del copy) fue el que hizo que no pudiésemos llamar a sendfile en el servidor.

Para resolver ambos problemas hicimos principalmente dos cosas. La primera de ellas fue llamar a la operación de copy solamente en el caso en que ambos ficheros son remotos. En caso contrario, se haría el tradicional read/write, como si se hubiese llamado a sendfile sin modificar.

Lo segundo que hicimos fue llamar a write localmente en lugar de utilizar directamente una RPC. De esta forma, si un ordenador no reexporta un fichero que se ha exportado previamente a sí mismo (un caso completamente anómalo), no puede suceder un bloqueo.

Medidas

Para medir las mejoras en velocidad introducidas por el uso de la nueva operación copy, teníamos que medir cuanto se tardaba en copiar un fichero en los dos casos en que copy funcionaba de forma diferente que sendfile (los dos casos en que ambos ficheros eran remotos). Un factor que había que tener en cuenta también era el uso de la caché (completamente crucial como vimos más adelante).

Para tomar las medidas utilizamos una red a 10Mb/s interconectando ordenadores con procesadores AMD K6/2 a 300MHz.

Para tener en cuenta la importancia de la caché, se hicieron las medidas en unos casos con el fichero en la caché (caché ``caliente'') y sin el fichero en la caché (caché ``fría''). También se hicieron medidas para diferentes tamaños de fichero. Los resultados de las medidas se pueden ver en las figuras 47

Para el caso de dos ordenadores, es obvio que ganamos más de un orden de magnitud en eficiencia al usar la operación de copia frente a read/write independientemente del estado de la caché. En el caso de tres ordenadores, también obtenemos beneficios si la caché está ``fría''. Sin embargo, en el caso de caché caliente, contrariamente a la intuición es más lento usar copy que read/write. Esto es debido a la combinación de caché y readahead. A pesar de esto y del alto grado de uso de la caché (tiene un porcentaje de uso del $90\%$ aproximadamente2 habilitamos el caso de tres ordenadores, porque en media se ganaba en velocidad (aunque fuese poco) y además se reduce el uso de recursos, memoria, red etc.

Figura: Copia entre dos máquinas usando R/W y Copy--con cache caliente y fria. (Ficheros pequeños)
\begin{figure}
\begin{center}
\epsfig {file=plot1.eps,width=10cm} \end{center}\end{figure}

Figura: Copia entre dos máquinas usando R/W y Copy--con cache caliente y fria. (Ficheros grandes)
\begin{figure}
\begin{center}
\epsfig {file=plot2.eps,width=10cm} \end{center}\end{figure}

Figura: Copia entre tres máquinas con R/W y Copy--cache caliente y fría. (Ficheros pequeños)
\begin{figure}
\begin{center}
\epsfig {file=plot3.eps,width=10cm} \end{center}\end{figure}

Figura: Copia entre tres máquinas con R/W y Copy--cache caliente y fría. (Ficheros grandes)
\begin{figure}
\begin{center}
\epsfig {file=plot4.eps,width=10cm} \end{center}\end{figure}



Notas al pie

... aproximadamente2
esto lo medimos con un kernel modificado en un laboratorio

next up previous
Siguiente: Lecciones aprendidas Superior: Mejorando NFS Anterior: Cambios que hemos hecho

Download this document: [src.tar.gz][ps.gz][html.tar.gz][dvi.gz]

Congreso HispaLinux 2000