Por que excluir arquivos grandes do tmpfs não é instantâneo?

1
$ cat /proc/mounts | egrep ' /tmp '
tmpfs /tmp tmpfs rw,nosuid,nodev,relatime 0 0
$ dd if=/dev/zero bs=1M count=3000 of=/tmp/q
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB) copied, 1.04961 s, 3.0 GB/s
$ time rm /tmp/q

real    0m0.296s
user    0m0.000s
sys     0m0.290s

Por que não 0.000s ? Não há disco envolvido, apenas marcando que a memória não é mais usada.

    
por Vi. 01.02.2016 / 21:41

1 resposta

5

O "marcar a memória como não utilizada" é uma função de quanto trabalho a chamada do sistema unlinkat(2) tem que fazer, que por sua vez, escala linearmente com o tamanho do arquivo. Para um padrão tmpfs em um sistema RHEL 6 com ~ 4G de memória, isso pode ser demonstrado da seguinte forma.

$ sudo mkdir /tmpfs; sudo mount -t tmpfs -o size=75% tmpfs /tmpfs; cd /tmpfs
$ dd if=/dev/zero bs=1M of=blah count=2859
...
$ strace -c rm blah 2>&1 | head -3
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.241964      241964         1           unlinkat
$ for c in 500 1000 1500 2000 2500; do dd if=/dev/zero bs=1M of=blah count=$c 2>/dev/null; echo -n "$c "; strace -c rm blah 2>&1 | awk '/unlinkat/{print $3}'; done
500 53992
1000 88986
1500 135980
2000 174974
2500 222966

Quanto ao que a chamada do sistema unlinkat(2) está fazendo em particular, isso exigiria uma pesquisa no código-fonte; Meu palpite é que a estrutura de dados que representa o arquivo na memória (uma lista encadeada?) está sendo colocada em loop quando o arquivo é removido, o que representa o crescimento linear do tempo de operação com o tamanho do arquivo.

    
por 01.02.2016 / 22:14