Transferencia de archivos a memoria USB muy lenta en Ubuntu Linux
De un tiempo para acá he notado en las últimas versiones de GNU/Linux una transferencia de archivos a memoria USB muy lenta, sobretodo en Debian, Ubuntu y sus derivados. Veamos entonces por qué suecede eso en una pendrive y su solución.
Sentimos nuestro sistema normal cuando copiamos pocos y pequeños archivos a nuestro pendrive (memoria USB). Pero cuando se trata de archivos grandes, sentimos que algo no anda bien, porque la velocidad de escritura en la USB no se sostiene, pues la vemos bajando a niveles de los KB/s. Incluso a veces vemos que sin razón queda como pausado. Entoces este aparente defecto se convierte en una incomodidad cuando estamos en un ambiente acadeḿico o productivo.
Causas de la transferencia de archivos a memoria USB muy lenta en Ubuntu
Pueden ser cuatro las causas de esta incomodidad:
- Un problema de velocidad en la misma memoria USB
- La caché de escritura de Linux.
- Defectos en el sistema de ficheros de la pendrive
- La memoria USB no es original
- Protección contra sobrecalentamiento en la memoria USB
Para poder realizar estos diagnósticos debemos tener clara la identificación de nuestra USB conectada en el sistema. Entonces nos valemos del siguiente comando:
sudo lsblk | grep -v '^loop' ó lsblk -p -e 7
El anterior comando muestra todos los medios de almacenamiento conectados a nuestro sistema, exceptuando los dispositivos loops de los paquetes Snap.
Nota: Nuestros documentos guardados en la pendrive se puede perder en estas operaciones.
Probar la velocidad de la memoria USB en Linux
1- Podemos verificar la velocidad de la memoria con el siguiente comando (en mi caso es /dev/sdb1):
sudo dd if=/dev/zero of=/dev/sdb1 bs=1M count=1024 oflag=direct
El anterior comando escribe directamente en la memoria USB un archivo de 1 GB, saltándose la caché de escritura de Linux. Ese proceso toma algunos minutos y luego nos muestra la velocidad de tranferencia real de la pendrive. Su velocidad debe ser razonablemente acorde con las especificaciones informadas por su fabricante. Ya descartado este punto, pasamos a probar el siguiente.
La caché de escritura de Linux
2- La caché de escritura en Ubuntu se ha vuelto la principal causa de la lentitud percibida, debido a que contamos con memorias de más capacidad. Cuando copias archivos, Ubuntu primero los almacena en la memoria RAM (en su caché) y luego los escribe en la memoria USB.
La barra de progreso de la transferencia puede mostrar una velocidad alta inicialmente mientras se llena la caché, pero se detiene o se vuelve muy lenta cuando el sistema operativo realmente comienza a vaciar la caché hacía la pendrive. Este proceso puede tardar un tiempo considerable, especialmente con archivos grandes, dando la sensación de que la transferencia está congelada o extremadamente lenta.
Incluso, a causa de la caché de escritura viene otro fenómeno cuando aparentemente ya hemos terminado de transferir los archivos. Se trata de la extración segura de la USB, que cuando le damos la orden a Ubuntu de extraer de forma segura el medio de almacenamiento, éste dice que no la desconectemos, que aún se están tranfiriendo archivos:
Y eso es normal porque efectivamente Linux no ha terminado de vacíar el contenido de la caché al medio de almacenamiento externo.
Resulta que Linux úbica dentro de su caché (en la RAM), los archivos que estamos copiando hacía la memoria USB. Luego, los transfiere a ésta última en ráfagas de paquetes. Exactamente!… la copia no es contínua (en el comando del primer paso hacemos que la copia sea continua con dd y la opción oflag=direct). Eso se hace así para prevenir bajonasos en el rendimiento del resto del sistema (podemos leer más al respecto en el sitio de Disk Manufacturer). Por eso la tranferencia de archivos grandes se pone lenta y hace que sintamos una mala experiencia.
Con un widget de monitoreo de medios de almacenamiento, como los que trae KDE Plasma, podemos visualizar dicho comportamiento (en mi caso mi pendrive tiene la etiqueta SOFTWARE):
En la imagen podemos ver los paquetes de información transferidos en ráfagas (los picos azules más pronunciados). Y podemos observar que hay mucho espacio inoficioso entre ráfagas, de ahí la lentitud.
Con los siguientes comandos podemos hacer una mejora para memorias USB formateadas con NTFS (estas pruebas toman efecto reconectando la pendrive al puerto):
echo 67108864 > /proc/sys/vm/dirty_bytes echo 16777216 > /proc/sys/vm/dirty_background_bytes
Esos dos comandos le dicen a Linux que no espere a que su caché se llene del todo, sino que cuando los archivos copiados lleguen a esos limites definidos en los comandos, los transfiera al medio de almacenamiento externo, entonces logramos reducir los espacios inoficiosos entre ráfagas. Y ahí lo tenemos, un proceso de transferencia optimizada:
Desafortunadamente hasta aquí llegamos con NTFS, pero podemos optimizar más parámetros para memorias formateadas con EXT4.
Optimizar la velocidad de copia en memoria USB con EXT4
Resulta que Linux controla la frecuencia de activación de los procesos encargados de la escritura en los medios de almacenamiento. Esa frecuencia está predeterminada a 500 (5 segundos).
Entonces tenemos de nuevo a nuestro widget mostrandonos una transferencia de archivos a memoria USB muy lenta en Ubuntu, con EXT4 (el espacio entre ráfagas también depende de los parámetros que vimos más arriba).
Con los siguientes comandos podemos reducir los tiempos de esa frecuencia:
sysctl -w vm.dirty_writeback_centisecs=30 sysctl -w vm.dirty_expire_centisecs=500
Y he aquí la tranferencia optimizada para memorias formateadas con EXT4, con los espacios más reducidos entre ráfagas:
Guardamos los valores de estos parámetros en el archivo /etc/sysctl.conf para que sean permanentes:
vm.dirty_bytes=67108864
vm.dirty_background_bytes=16777216
vm.dirty_writeback_centisecs=30
vm.dirty_expire_centisecs=500
Mi memoria USB ajustada a una velocidad de 4 MB/s
Casi todas las memorias USB que encontramos en el mercado vienen con una protección de sobrecalentamiento. Tal protección tiene los siguientes efectos:
- Reducción automática de velocidad (thermal throttling). Algunas memorias USB reducen la velocidad de escritura cuando la temperatura aumenta demasiado. Esto evita daños al controlador y a la memoria flash.
- Desconexión temporal. Algunos controladores USB incorporan protección térmica y pueden dejar de responder o desconectarse temporalmente si alcanzan una temperatura crítica. Después de enfriarse, suelen volver a funcionar
Todas las memorias USB tienen esas características de protección, lo que sucede es que las memorias falsificadas ó baratas son más problemáticas con altas tasas de escritura.
Gracias al comando rsync me di cuenta que mi memoria USB no activa la protección de sobrecalentamiento, cuando le defino una velocidad de escritura a 4 MB/s. A más velocidad, se reduce drasticamente su velocidad. ¿cómo me di cuenta?, usando a rsync así:
rsync -ah --progress --bwlimit=la_velocidad_en_kbytes /archivos_origen /carpeta_destino
Comencé con una velocidad alta (10 MB/s) y copiando 20 archivos de entre 11 y 60 MB (600 MB de información), y ví que a partir del archivo 14 comienza a flaquear la escritura (por la protección) y la suma de los tiempos dio 6 minutos de copia en la memoria USB:
rsync -ah --progress --bwlimit=10000 /archvivos_origen /carpeta_destino
Tanteando varias velocidades, me di cuenta que con 4 MB/s el flujo de escritura se mantiene constante y los tiempos dan como resultado 3 minutos de copia en la memoria USB:
rsync -ah --progress --bwlimit=4000 /archviso_origeb /carpeta_destino
Entonces ese es el balance que debemos encontrar. Pero la memoria USB es nuestra y de uso permanente, no nos la podemos pasar copiando con el comando rsync. Vamos a personalizar el menú contextual en KDE Plasma con la siguiente solución para copiar archivos en esas memorias USB problemáticas:
a- Instalamos zenity y kdialog para la interfaz de la solución sudo apt install zenity kdialog
b- Creamos el menú contextual
nano .local/share/kio/servicemenus/copiar_usb_directo.desktop
Le ponemos esta parametrización:
[Desktop Entry] Type=Service ServiceTypes=KonqPopupMenu/Plugin MimeType=all/allfiles;inode/directory; Actions=CopiarenUSBproblematica; X-KDE-Submenu=Copia a USB regulada [Desktop Action CopiarenUSBproblematica] Name=Copiar a USB Icon=drive-removable-media Exec=/home/mi_usuario/copiar-usb-directo.sh %U
Le damos permiso de ejecución:
chmod +x .local/share/kio/servicemenus/copiar_usb_directo.desktop
c- Creamos el script copiar-usb-directo.sh (puede ser en nuestro home directory) que será el que reciba los nombres de los archivos como parámetro, para realizar la copia con rsync.
#!/bin/bash set -u ORIGENES=() for arg in "$@"; do ruta="${arg#file://}" ruta="$(echo -e "${ruta//%/\\x}")" [ -e "$ruta" ] && ORIGENES+=("$ruta") done [ ${#ORIGENES[@]} -eq 0 ] && { zenity --error --text="No se recibió ningún archivo o carpeta válida." exit 1 } DESTINO_DIR=$(zenity --file-selection --directory \ --title="Selecciona la memoria USB destino" \ --filename="/mnt/") [ -z "$DESTINO_DIR" ] && exit 0 [ ! -w "$DESTINO_DIR" ] && { zenity --error --text="No tienes permisos de escritura en:\n$DESTINO_DIR" exit 1 } # Calcular total de archivos para el progreso TOTAL_ARCHIVOS=0 for f in "${ORIGENES[@]}"; do if [ -d "$f" ]; then N=$(find "$f" -type f | wc -l) else N=1 fi TOTAL_ARCHIVOS=$((TOTAL_ARCHIVOS + N)) done ( COPIADOS=0 i=0 for ORIGEN in "${ORIGENES[@]}"; do i=$((i+1)) NOMBRE=$(basename "$ORIGEN") # Borrar destino si existe (fuerza sobrescritura) DESTINO="$DESTINO_DIR/$NOMBRE" [ -e "$DESTINO" ] && rm -rf "$DESTINO" # Copiar con rsync y parsear cada archivo conforme se procesa rsync -a --no-inc-recursive --bwlimit=4000 \ --out-format='%n' \ "$ORIGEN" "$DESTINO_DIR/" 2>&1 | while IFS= read -r line; do # Ignorar líneas vacías y líneas de rsync que no son nombres [ -z "$line" ] && continue [[ "$line" == sending* ]] && continue [[ "$line" == ./ ]] && continue COPIADOS=$((COPIADOS + 1)) PCT=$((COPIADOS * 100 / TOTAL_ARCHIVOS)) echo "$PCT" echo "#[$COPIADOS/$TOTAL_ARCHIVOS] $line" done # Sincronizar después de cada item grande sync done echo "100" echo "#¡Copia finalizada!" ) | zenity --progress \ --title="Copia Segura a USB" \ --text="Preparando copia..." \ --percentage=0 \ --auto-close kdialog --passivepopup "¡Copia finalizada!" 5
Guardamos y también le damos permiso de ejecución. Y como último paso reiniciamos a Dolphin.
kquitapp5 dolphin 2>/dev/null || pkill -f dolphin; dolphin & disown
Y ahí lo tenemos
Pero a veces podemos dar con una memoria USB que ni fijandole una velocidad de escritura menor funciona bien, y podríamos estar frente a una memoris USB falsa. Por eso, en el siguiente artículo podemos ver cómo detectar una memoria USB falsa









