Perché la cancellazione dei file per nome è dolorosamente lenta e anche eccezionalmente veloce?


11

Faux pas: Il metodo "veloce" che cito di seguito, non è 60 volte più veloce di quello lento. È 30 volte più veloce. Incolperò l'errore ogni ora (3AM non è il mio momento migliore della giornata per pensare chiaramente :) ..

Aggiornamento: ho aggiunto un riepilogo dei tempi di prova (sotto).
Sembra che ci siano due problemi coinvolti con il fattore velocità:

  • La scelta del comando utilizzato (Confronti temporali mostrati di seguito)
  • La natura di un gran numero di file in una directory ... Sembra che "big is bad". Le cose diventano sproporzionatamente più lente quando i numeri aumentano.

Tutti i test sono stati eseguiti con 1 milione di file.
(i tempi reali, utente e sys sono negli script di test)
Gli script di test sono disponibili su paste.ubuntu.com

#
# 1 million files           
# ===============
#
#  |time   |new dir   |Files added in  ASCENDING order  
#  +----   +-------   +------------------------------------------------- 
#   real    01m 33s    Add files only (ASCENDING order) ...just for ref.
#   real    02m 04s    Add files, and make 'rm' source (ASCENDING order) 
#                      Add files, and make 'rm' source (DESCENDING order) 
#   real    00m 01s    Count of filenames
#   real    00m 01s    List of filenames, one per line
#   ----    -------    ------
#   real    01m 34s    'rm -rf dir'
#   real    01m 33s    'rm filename' via rm1000filesPerCall   (1000 files per 'rm' call)
#   real    01m 40s    'rm filename' via  ASCENDING algorithm (1000 files per 'rm' call)
#   real    01m 46s    'rm filename' via DESCENDING algorithm (1000 files per 'rm' call)
#   real    21m 14s    'rm -r dir'
#   real    21m 27s    'find  dir -name "hello*" -print0 | xargs -0 -n 1000 rm'
#   real    21m 56s    'find  dir -name "hello*" -delete'
#   real    23m 09s    'find  dir -name "hello*" -print0 | xargs -0 -P 0 rm'
#   real    39m 44s    'rm filename' (one file per rm call) ASCENDING
#   real    47m 26s    'rm filename' (one file per rm call) UNSORTED
#                                                       

Di recente ho creato ed eliminato 10 milioni di file di test vuoti. Eliminando i file in base al nome (ad es. rm filename), Ho scoperto che esiste una differenza di tempo enorme tra 2 metodi diversi ...

Entrambi i metodi usano lo stesso rm filenamecomando esatto .

Aggiornamento: a quanto pare, i comandi non erano esattamente gli stessi ... Uno di questi stava inviando 1000 nomi di file alla volta a "rm" ... Era un problema di espansione della shell dove pensavo che ogni nome di file fosse stato scritto al file dell'alimentatore su una riga a sé stante, ma in realtà era 1000 per riga

I nomi dei file vengono forniti tramite un "file feeder" in un while readciclo.
Il file feeder è l'output di ls -1 -f
I metodi sono identici sotto tutti gli aspetti, ad eccezione di una cosa:

  • il metodo lento utilizza direttamente il file feeder non ordinatols -1 -f
  • il metodo veloce utilizza una versione ordinata dello stesso file non ordinato

Non sono sicuro che l'ordinamento sia il problema qui, o forse è che il file dell'alimentatore ordinato coincide solo con la sequenza in cui sono stati creati i file (ho usato un semplice algoritmo intero crescente)

Per 1 milione di file, il metodo veloce rm filename è 60 volte più veloce del metodo lento ... di nuovo, non so se si tratta di un problema di "ordinamento" o di un problema di tabella hash dietro le quinte ... non è un semplice problema di ordinamento, perché perché ls -1 -fmi darebbe intenzionalmente un elenco non ordinato di una sequenza di nomi di file "ordinati" appena aggiunta ...

Mi sto solo chiedendo cosa sta succedendo qui, quindi non mi ci vogliono giorni (sì giorni) per eliminare i prossimi 10 milioni di file :) .... Dico "giorni" perché ho provato così tante alternative, e il i tempi coinvolti aumentano in modo sproporzionato rispetto al numero di file in questione .. quindi ho testato solo 1 milione in dettaglio

A proposito: l'eliminazione dei file tramite l'elenco "ordinato" dei nomi è in realtà più rapida di rm -rfun fattore 2
e: rm -r30 volte più lenta del metodo "elenco ordinato"

... ma il problema è "risolto" qui? o è più correlato a un metodo di memorizzazione hashing (o altro) utilizzato da ext4?

La cosa che mi confonde abbastanza è che ogni chiamata a rm filenamenon è correlata alla precedente .. (beh, almeno è così dalla prospettiva 'bash')

Sto usando Ubuntu / bash / 'ext4' / unità SATA II.


1
Lo stai facendo male! (tm) Ne hai mai sentito parlare find -delete?
alex

I tuoi 2 test iniziano in condizioni ineguali (non pretendo che questo sia davvero importante): uno legge i nomi dei file da un file e l'altro legge i nomi dei file da un file che è stato creato (ordinato) immediatamente prima del test. Potrebbe essere che il file che viene memorizzato nella cache nel secondo caso riproduca alcuni (o forse no, chissà). Affinché i test siano in condizioni più uguali, forse dovresti fare un semplice catda un file nuovo prima del 1 ° test - al posto di sortprima del 2 ° test.
imz - Ivan Zakharyaschev,

E ti consiglio di presentare le tue osservazioni e le tue domande in modo più chiaro. Per favore, una cosa alla volta: confronta solo 2 casi in una domanda, porta in primo piano i due casi importanti, tutto il resto sono solo informazioni di base; per favore, chiariscilo. Non mescolare più osservazioni in un solo post, per favore.
imz - Ivan Zakharyaschev,

Presentare il sistema e il tempo dello spazio utente dal tuo potrebbe anche essere importante per risolvere il puzzle, quindi includili nella tua domanda. Quale di questi fa la differenza nei tuoi test?
imz - Ivan Zakharyaschev,

1
L'ottimizzazione prematura è la radice di tutti i mali. :) Quando cancellerai mai 10 milioni di file? 100000 al secondo mi sembrano abbastanza veloci (per rovinare il tuo sistema).
utente sconosciuto

Risposte:


2

rm -r dovrebbe essere lento come ricorsivo. È necessario effettuare una prima traversata approfondita sulla struttura delle directory.

Ora come hai creato 10 milioni di file? hai usato qualche script che scorre in qualche ordine? 1.txt, 2.txt, 3.txt ... se sì, anche quei file possono essere allocati nello stesso ordine in blocchi contigui in hdd.so l'eliminazione nello stesso ordine sarà più veloce.

"ls -f" abiliterà -aU che elenca in ordine di directory che è di nuovo ricorsivo.


1
McAlot: Non riesco a capire quanto 'ricorsivo' sia importante in questo caso , dato che non ci sono sottodirectory coinvolte ... Sì, ho usato "1.txt, 2.txt, 3.txt". Forse ci sono molti cose che interagiscono: ad esempio, perché ci vuole solo 1min 30s per creare 1 milione di file, ma ci vuole 10s 7m per creare 2 milioni e dopo di loro eliminazione, ricreando le 1 milione. molto richiede più tempo (30s 9m) la sua strana, tutto è in funzione lentamente all'improvviso. Anche questo è successo prima. Penso che (?) l'eliminazione della directory sia stata
corretta

In generale, i filesystem non sono ottimizzati per gestire un numero elevato di file nella stessa directory. Non ho familiarità con ext4 in particolare, ma per altri formati le voci della directory sono state contrassegnate come inutilizzate quando i file sono stati eliminati. Ciò significa che devono comunque essere ignorati quando si eseguono operazioni nella directory. Ciò spiegherebbe il comportamento che stai vedendo.
KeithB

1
Ho cancellato la directory "ora più lenta" e ho usato un nome diverso per una nuova directory. Il tempo necessario per creare 1 milione di file è ora tornato a 1m 33s (contro 9m 30s quando la directory "contiene" 2 milioni di file eliminati, il primo milione ha lo stesso nome del 1 milione appena aggiunto) ... interessante, e risponde al tuo commento "... appena contrassegnato come inutilizzato" ... come arrivare; sta iniziando a dare un senso :)
Peter

@ fred.bear Mio male, non sapevo davvero la gerarchia reale e la mia risposta era indovinare. anche il tuo test in realtà sottolinea i metadati ma non i file reali in quanto sono file vuoti. Il modo migliore per confrontare questo tipo di problema è prendere i file da / var o cache del web server. comunque anche il tuo test sembra interessante, puoi provare a cancellare con due metodi elencati in directory diverse ... come /sample1/1.txt,2.txt ... e /sample2/1.txt,2.txt ..
rajaganesh87

@ Mr.Confused.A.Lot ... Grazie per l'aiuto. La tua spiegazione mi ha aiutato a capire meglio il filesystem e alcuni dei suoi manierismi ... Ora ho un'idea ragionevole di ciò che stava causando i diversi problemi di velocità ... Alcuni erano solo una scelta di comandi bash, e altri erano semplicemente problemi del filesystem ( Mi rimane un nuovo motto: "big is bad" per le directory ... (almeno per alcune azioni) ...
Peter.O

2

È necessario ottimizzare la struttura del file. Quindi invece di

for i in $(seq 1 1000); do touch file.$i; done

fare qualcosa di più intelligente (bash ipotizzato):

function bucklocate() 
{ 
    hash=$(echo -n "$1"|md5sum|cut -f1); 
    echo -n "${hash:1:1}/${hash:7:1}/${hash:9:2}/$1"; 
}

hexdig="{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}"
eval mkdir -p $hexdig/$hexdig/$hexdig$hexdig


for i in $(seq 1 1000); do touch $(bucklocate file.$i); done

Ora questo esempio è piuttosto lento a causa dell'uso di md5sum [1], usa qualcosa come il seguente per una risposta molto più veloce, finché non hai bisogno di nomi di file particolari, i duplicati non sono preoccupanti e non c'è bisogno di un hash ripetibile di un certo nome :)

mkdir -pv {0,1,2,3,4,5,6}/{0,1,2,3,4,5,6,7,8,9,10,12}
for  a in $(seq 1 100); do i=$RANDOM; echo touch "$(($i%7))/$(($i%13))/file.$i"; done

Ovviamente si tratta di tutti i concetti mutuatamente trascurati dagli hashtabili


Penso che tu stia dicendo "usa directory più piccole" ... È un'idea interessante; un DBMS cresciuto in casa che crea un albero da un gruppo di file "senza alberi". Alcuni potrebbero chiamarlo pianificazione in avanti :) ... Se funziona (e probabilmente funziona), allora è una buona idea ! :) ... Sto iniziando ad avere l'idea che 'big is bad' quando si tratta del numero di file in una directory (almeno per ext4) ... Hai presentato una soluzione preventiva (+1) e io '
Mi sto

Sì, mi dispiace di non essere più esplicito sull'idea di mantenere le regette piccole
vedi il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.