Uno de los mayores desafíos que nos encontramos ante un problema de rendimiento en nuestras aplicaciones o sistemas, se produce cuando dicho problema está en una capa que de forma habitual tiene un comportamiento adecuado y necesitamos trabajar con herramientas cuyo uso no es tan habitual.
En este post, vamos a ahondar en alguna de estas herramientas y métodos cuando nos enfrentamos ante un problema de rendimiento de discos en sistemas Linux.
¿Cómo identificar problemas de I/O en Linux?
Para hacer una detección básica del rendimiento de un disco en un sistema Linux/Unix e identificar problemas de escritura, podemos seguir estos sencillos pasos para hacer un primer diagnóstico a nivel básico.
Identificación de volúmenes
Lo primero es identificar los volúmenes que tenemos disponibles y sobre los que queremos operar:
[root@xxxxxxxxxx]/root# df -k Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda3 11025272 8604420 1851752 83% / /dev/sda7 10153988 1599432 8030440 17% /usr /dev/sda6 10153988 951912 8677960 10% /var /dev/sda5 20315812 16919124 2348048 88% /u01 /dev/sda1 194442 11887 172516 7% /boot tmpfs 10245144 0 10245144 0% /dev/shm /dev/appjava1 51606124 33864592 15120096 70% /oracle/oas10gR3 /dev/appforms1 51606124 13161444 35823244 27% /oracle/appserver
Test de rendimiento
Una vez tenemos los discos (/dev) y los puntos de montaje, comenzamos a probar el rendimiento de cada uno de ellos realizando una escritura intensiva sobre los mismos:
for i in 1 2 3 4 5 6 7 8 9 10; do dd if=/dev/zero of=/write.img bs=8k count=256k conv=fdatasync done
En ese script sustituimos "/write.img" por el filesystem donde queremos escribir que se corresponderá con el que estamos analizando. Este comando realizará 10 iteraciones escribiendo un fichero de pruebas de 2gb de forma sostenida y nos dará un resultado como este:
262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GB) copied, 20.451 s, 98 MB/s 262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GB) copied, 20.4202 s, 101 MB/s .....
El comando hará 10 iteraciones ya que, si bien las primeras puede dar unos buenos resultados, a medida que el buffer de escritura del disco se va llenando, y no ser capaz de escribir a una velocidad suficiente, dicha tasa de escritura desciende, y arrojará un resultado como éste:
262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GG) copied, 81.5432 s, 24.2 MB/s 262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GB) copied, 108.41 s, 19.8 MB/s
Análisis del test
Revisando en detalle las tasas de velocidad, se ve claramente la drástica reducción de rendimiento, motivado porque estamos saturando el I/O del disco.
Los valores de rendimiento en Mb/s dependerán mucho del disco en si y de su arquitectura (nas, san, scsci, ...) y los valores pueden variar enormemente, es decir, una tasa de escritura lenta, no tiene que significar siempre un problema si ésta se mantiene estable durante la prueba.
De cualquier forma, durante la misma, podemos ejecutar el siguiente comando desde otro terminal y poder ver en tiempo real el rendimiento de los dispositivos en análisis:
iostat -d -m -x 2 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util sda 0.00 6.50 0.00 5.00 0.00 0.04 18.40 0.03 5.60 5.00 2.50 sda1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sda2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sda3 0.00 5.50 0.00 2.00 0.00 0.03 30.00 0.01 6.50 5.00 1.00 sda4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 sda5 0.00 1.00 0.00 3.00 0.00 0.02 10.67 0.01 5.00 5.00 1.50
En ella podemos ver el comportamiento del disco para que en caso de que tengamos una tasa de escritura lenta, obtengamos detalle de las distintas operaciones y así, ayudar a determinar el origen del problema de rendimiento.
Ejemplo práctico
Si estamos identificando una tasa de escritura lenta, nos debemos fijar en los datos que nos arroja el comando descrito en el punto anterior.
Por ejemplo, ejecutamos la secuencia completa en un entorno:
[root@xxxxxxxx]/root# for i in 1 2 3; do > dd if=/dev/zero of=/write.img bs=8k count=256k conv=fdatasync > done 262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GB) copied, 22.2793 seconds, 96.4 MB/s 262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GB) copied, 22.2579 seconds, 96.5 MB/s 262144+0 records in 262144+0 records out 2147483648 bytes (2.1 GB) copied, 22.8519 seconds, 94.0 MB/s
Vemos que se mantiene en una tasa sostenida (solo hemos hecho 3 iteraciones con una tasa de alrededor de 95 MB/s), mientas que el iostat, nos arroja los siguientes resultados:
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util sda 0.00 25837.50 0.00 689.00 0.00 102.58 304.91 143.01 207.15 1.45 100.05
Como vemos, en dicho disco, tenemos las tasas de escritura como en el comando anterior, pero los valores que nos interesan más por su significado, son el await y el %util:
- await es el tiempo en milisegundos que el disco está tardando en procesar las peticiones de I/O.
- %util el tiempo que el disco está en uso.
Normalmente, a medida que la cola se va llenando, el rendimiento del disco empeora, es decir, que no importa que el uso esté al 100% y haya cierto await, mientras los valores no crezcan demasiado y empiece a bajar la tasa de transferencia en Mb/s.
Un disco sin problemas, tendría este aspecto, si lanzamos un iostat con opciones 2 10:
[root@xxxxxxx]/root# iostat 2 10 Linux 2.6.18-194.el5 (xxxxxxxx) 05/23/2016 avg-cpu: %user %nice %system %iowait %steal %idle 0.40 0.03 0.19 0.67 0.00 98.71
Mientras que un entono con problemas tendría este aspecto:
CPU %user %nice %system %iowait %steal %idle all 1.25 0.00 2.50 70.00 0.00 26.25
Donde vemos que la máquina apenas tiene carga (CPU por debajo del 5%) y tiene un iowait del 70%.
Una vez identificado que el sistema tiene algún problema relacionado con las esperas de I/O, podemos ir al detalle de los distintos discos de dicho sistema:
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util sda 0.00 0.50 0.00 0.60 0.00 0.00 12.00 1.73 3664.67 1668.67 100.02 dm-2 0.00 0.00 0.00 673.13 0.00 2.63 8.00 11734.53 21798.66 1.49 100.02
Y ahí es donde podemos identificar que tenemos un problema de escritura en disco.
Los siguientes pasos, en un caso como éste, continúan con la investigación del disco identificado con problemas de escritura que pueden ser de diferentes tipos y, por tanto, con diferentes tipos de soluciones:
- El disco no está preparado para las labores que se necesitan realizar (escritura intensiva)
- Configuración no adecuada del disco
- Configuración del sistema operativo
- Cabina de discos
- Drivers
Conclusiones
Ante un problema de rendimiento de una aplicación, lo primero de todo, es identificar el origen del problema. En este caso, nos hemos centrado en un problema relacionado con los discos de un sistema montado con Linux.
Este sistema operativo nos proporciona unas herramientas bastante útiles para la realización de un test de rendimiento y detallar el comportamiento de los discos y así poder acotar el origen del problema de rendimiento de nuestra aplicación.