Вы можете прекратить использование файла подкачки и занять память другими программами.
swapoff -a
Для получения дополнительной информации прочтите man swapon
или man swapoff
Или настройте виртуальную машину с меньшим объемом оперативной памяти. Это немного больше работы, но, вероятно, полезно в долгосрочной перспективе, но означает, что вам нужен ЦП, поддерживающий виртуальные машины.
La principal diferencia entre abrir el archivo antes del ciclo con exec
y poner la redirección en el comando en el ciclo es que el primero requiere configurar el descriptor de archivo solo una vez, mientras que el segundo abre y cierra el archivo para cada iteración del bucle.
Es probable que hacerlo una vez sea más eficiente, pero si tuviera que ejecutar un comando externo dentro del ciclo, la diferencia probablemente desaparecería en el costo de ejecutar el comando.(echo
aquí probablemente esté integrado, por lo que no se aplica)
Si la salida se va a enviar a algo que no sea un archivo normal (p. si x
es una tubería con nombre ), el acto de abrir y cerrar el archivo puede ser visible para otros procesos, por lo que también puede haber diferencias en el comportamiento.
Tenga en cuenta que realmente no hay diferencia entre una redirección a través de exec
y una redirección en el comando, ambos abren el archivo y hacen malabarismos con los números de descriptor de archivo.
Estos dos deberían ser bastante equivalentes, ya que ambos open()
el archivo y write()
a él. (Sin embargo, hay diferencias en cómo se almacena fd 1 durante la duración del comando.):
for i in {1..1000}; do
>>x echo "$i"
done
for i in {1..1000}; do
exec 3>&1 1>>x # assuming fd 3 is available
echo "$i" # here, fd 3 is visible to the command
exec 1>&3 3>&-
done
Sí, es más eficiente
La forma más fácil de probar es aumentar el conteo para decir 500000 y cronometrarlo:
> time bash s1.sh; time bash s2.sh
bash s1.sh 16,47s user 10,00s system 99% cpu 26,537 total
bash s2.sh 10,51s user 3,50s system 99% cpu 14,008 total
strace (1 )revela por qué (tenemos uno simple write
, en lugar de open
+5*fcntl
+2*dup
+2*close
+write
):
para for i in {1..1000}; do >>x echo "$i"; done
obtenemos:
open("x", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
fcntl(1, F_GETFD) = 0
fcntl(1, F_DUPFD, 10) = 10
fcntl(1, F_GETFD) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
write(1, "997\n", 4) = 4
dup2(10, 1) = 1
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
open("x", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
fcntl(1, F_GETFD) = 0
fcntl(1, F_DUPFD, 10) = 10
fcntl(1, F_GETFD) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
write(1, "998\n", 4) = 4
dup2(10, 1) = 1
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
open("x", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
fcntl(1, F_GETFD) = 0
fcntl(1, F_DUPFD, 10) = 10
fcntl(1, F_GETFD) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
write(1, "999\n", 4) = 4
dup2(10, 1) = 1
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
open("x", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
fcntl(1, F_GETFD) = 0
fcntl(1, F_DUPFD, 10) = 10
fcntl(1, F_GETFD) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
write(1, "1000\n", 5) = 5
dup2(10, 1) = 1
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
mientras que para exec 3>&1 1>x
quedamos mucho más limpios
write(1, "995\n", 4) = 4
write(1, "996\n", 4) = 4
write(1, "997\n", 4) = 4
write(1, "998\n", 4) = 4
write(1, "999\n", 4) = 4
write(1, "1000\n", 5) = 5
Pero tenga en cuenta que la diferencia no se debe a "usar un FD", sino al lugar donde realiza la redirección. Por ejemplo, si tuviera que hacer for i in {1..1000}; do echo "$i"; done > x
, obtendría prácticamente el mismo rendimiento que su segundo ejemplo:
bash s3.sh 10,35s user 3,70s system 100% cpu 14,042 total
Para resumir las cosas y agregar un poco de información nueva en este hilo, aquí hay una comparación de cuatro formas de hacerlo, ordenadas por eficiencia. Estimo la eficiencia por medición de tiempo (usuario + sys )para 1 millón de iteraciones, basado en dos series de prueba.
>
redirección de bucle (tiempo:100%)exec
una vez para todo el ciclo (tiempo:~100%)>>
para cada iteración (tiempo:200% -250%)exec
para cada iteración (tiempo:340% -480%)La conclusión es esta:
Hay una pequeña diferencia entre usar exec
y redirecciones simples como >>
. (Lo simple es más barato ). No se muestra en el nivel de ejecución de un solo comando, pero con una gran cantidad de repeticiones, la diferencia se vuelve visible. Aunque el peso de ejecución del comando redirigió a las sombras las diferencias, como lo notó ikkachu en la otra respuesta.