Dovrei usare Python o Assembly per un programma di copia super veloce




(11)

Non credo che farà una differenza percepibile quale lingua usi per questo scopo. Il collo di bottiglia qui non è la tua applicazione ma le prestazioni del disco.

Solo perché un linguaggio è interpretato, non significa che ogni singola operazione in esso sia lenta. Ad esempio, è una scommessa abbastanza sicura che il codice di livello inferiore in Python chiamerà il codice assembly (o compilato) per fare copia.

Allo stesso modo, quando fai roba con collezioni e altre librerie in Java, questo è per lo più compilato C, non interpretato Java.

Ci sono un paio di cose che puoi fare per velocizzare il processo.

  • Acquista dischi rigidi più veloci (10K RPM anziché 7.5K o meno latenza, cache più grandi e così via).
  • La copia tra due dischi fisici potrebbe essere più veloce della copia su un singolo disco (a causa del movimento della testa).
  • Se stai copiando attraverso la rete, mettilo in scena. In altre parole, copialo velocemente su un altro disco locale, quindi rallenti da lì attraverso la rete.
  • Puoi anche metterlo in scena in un modo diverso. Se si esegue un processo notturno (o anche settimanale) per mantenere aggiornata la copia (solo copia dei file modificati) anziché tre volte all'anno, non ci si troverà in una situazione in cui è necessario copiare una quantità enorme.
  • Inoltre, se si utilizza la rete, eseguirla sulla casella in cui si trova il repository. Non si desidera copiare tutti i dati da un disco remoto a un altro PC e quindi tornare a un altro disco remoto.

Puoi anche fare attenzione con Python. Potrei sbagliarmi (e senza dubbio i Pythonistas mi metteranno in chiaro se mi sbaglio su questo conteggio) ma ho un vago ricordo che il suo threading potrebbe non utilizzare completamente CPU multi-core. In tal caso, staresti meglio con un'altra soluzione.

Potresti star meglio ad attaccarti con la tua attuale soluzione. Sospetto che un programma di copia specializzato sarà già ottimizzato il più possibile dal momento che è quello che fanno .

Come problema di manutenzione, ho bisogno di eseguire regolarmente (3-5 volte all'anno) un repository che ora ha oltre 20 milioni di file e supera 1,5 terabyte nello spazio totale su disco. Attualmente sto usando RICHCOPY, ma ne ho provati altri. RICHCOPY sembra il più veloce ma non credo di avvicinarmi ai limiti delle capacità della mia macchina XP.

Sto giocando con ciò che ho letto in The Art of Assembly Language per scrivere un programma per copiare i miei file. Il mio altro pensiero è di iniziare a imparare come multi-thread in Python per fare le copie.

Sto giocando con l'idea di fare questo in Assembly perché sembra interessante, ma mentre il mio tempo non è incredibilmente prezioso è abbastanza prezioso che sto cercando di capire se vedrò o no dei guadagni abbastanza significativi in ​​velocità di copia . Presumo che lo farei, ma ho solo iniziato a imparare davvero a programmare 18 mesi ed è ancora più o meno un hobby. Quindi potrei mancare qualche concetto fondamentale di ciò che accade con i linguaggi interpretati.

Eventuali osservazioni o esperienze sarebbero apprezzate. Nota, non sto cercando alcun codice. Ho già scritto un programma di copia di base in Python 2.6 che non è più lento di RICHCOPY. Sto cercando alcune osservazioni su cui mi darà più velocità. In questo momento mi ci vogliono più di 50 ore per fare una copia da un disco a un Drobo e poi di nuovo da Drobo a un disco. Ho un LogicCube per quando sto semplicemente duplicando un disco ma a volte ho bisogno di passare da un disco a Drobo o viceversa. Sto pensando che dato che posso copiare un disco 3/4 full 2 ​​terabyte usando il LogicCube in meno di sette ore dovrei essere in grado di avvicinarmi a quello usando Assembly, ma non so abbastanza per sapere se questo è valido . (Sì, a volte l'ignoranza è beatitudine)

Il motivo per cui ho bisogno di accelerarlo è che ho avuto due o tre cicli in cui qualcosa è successo durante la copia (cinquanta ore sono lunghe per aspettare che il mondo si fermi) che mi ha costretto a buttare giù la copia e ricominciare . Ad esempio, la scorsa settimana il conduttore dell'acqua si è rotto sotto il nostro edificio e ha interrotto la corrente.

Grazie per le prime risposte ma non penso che si tratti di limitazioni I / O. Non sto andando su una rete, l'unità è collegata alla scheda madre con una connessione SATA e il mio Drobo è collegato a una porta Firewire, il mio pensiero è che entrambe le connessioni dovrebbero consentire un trasferimento più veloce.

In realtà non posso usare una copia di settore eccetto passare da un singolo disco a Drobo. Non funzionerà dall'altra parte poiché la struttura dei file Drobo è un mistero. La mia osservazione non scientifica è che la copia da un disco interno a un altro non è più veloce di una copia da o verso Drobo su un disco interno.

Sono legato all'hardware, non posso permettermi i dischi da 10K rpm da 2 terabyte (se li fanno anche loro).

Alcuni di voi suggeriscono una soluzione di sincronizzazione dei file. Ma questo non risolve il mio problema. Prima di tutto, le soluzioni di sincronizzazione dei file con cui ho giocato costruiscono una mappa (per mancanza di un termine migliore) dei dati prima, ho troppi piccoli file in modo che soffochino. Uno dei motivi per cui utilizzo RICHCOPY è che inizia a copiare immediatamente, non utilizza la memoria per costruire una mappa. Secondo, ho avuto uno dei miei tre backup Drobo fallire un paio di settimane fa. La mia regola è che se ho un errore di backup gli altri due devono rimanere fuori linea fino a quando il nuovo non viene costruito. Quindi ho bisogno di copiare da una delle tre copie di backup su disco singolo che ho che uso con LogicCube.

Alla fine della giornata devo avere una buona copia su una singola unità perché è quello che consegna ai miei clienti. Perché i miei clienti hanno sistemi diversi che consegna a loro su dischi SATA.

Affido lo spazio cloud a qualcuno in cui i miei dati vengono anche archiviati come il backup più profondo, ma è costoso estrarlo se non di lì.


Prima di mettere in dubbio l'app per la copia, è molto probabile che dovresti mettere in discussione il percorso dei dati. Quali sono i limiti teorici e cosa stai ottenendo? Quali sono i potenziali colli di bottiglia? Se esiste un singolo percorso di dati, probabilmente non si otterrà una spinta significativa parallelizzando le attività di archiviazione. Potresti addirittura esacerbare. La maggior parte dei vantaggi che si ottengono con l'I / O asincrono avviene a livello di blocco, un livello inferiore rispetto al file system.

Una cosa che potresti fare per potenziare I / O è separare il recupero dalle parti di origine e di archiviazione in quella di destinazione. Supponendo che l'origine e la destinazione siano entità separate, potresti teoricamente dimezzare la quantità di tempo per il processo. Ma gli strumenti standard lo stanno già facendo ??

Oh - e su Python e GIL - con l'esecuzione di I / O-bound, il GIL non è poi così male di una penalità.


La copia dei file è un processo legato all'I / O. È improbabile che si verifichi un aumento della velocità di riscrittura in assembly e persino il multithreading potrebbe causare un rallentamento delle cose in quanto thread diversi che richiedono file diversi nello stesso momento comporteranno più ricerche sul disco.

Utilizzare uno strumento standard è probabilmente il modo migliore per andare qui. Se c'è qualcosa da ottimizzare, potresti prendere in considerazione la possibilità di cambiare il tuo file system o il tuo hardware.


Da quando ho postato la domanda, ho giocato con alcune cose e penso innanzitutto di non essere polemico, ma quelli di voi che hanno pubblicato la risposta che sono rilegato sono solo parzialmente corretti. È il tempo di ricerca che è il limite. Una lunga storia per testare varie opzioni Ho costruito una nuova macchina con un processore I-7 e una scheda madre ragionevolmente potente / funzionale e quindi utilizzando le stesse due unità con cui stavo lavorando prima di notare un aumento della velocità abbastanza significativo. Ho anche notato che quando trasferisco file di grandi dimensioni (un gigabyte o giù di lì) ottengo velocità di trasferimento sostenute superiori a 50 Mb / se la velocità si riduce notevolmente quando si spostano file di piccole dimensioni. Penso che la differenza di velocità sia dovuta a un disco non ordinato rispetto al modo in cui il programma di copia legge la struttura della directory per determinare i file da copiare.

Quello che penso debba essere fatto è quello di 1: leggere la MFT e ordinare per settore lavorando dall'esterno all'interno del piatto (significa che devo capire come funzionano i dischi multi-piatto) 2: Analizzare e separare tutti i contigui contro file non contigui. Gestirei prima i file contigui e tornare indietro per gestire i file non contigui 3: iniziare a copiare i file contigui dall'esterno verso l'interno 4. Al termine copiare i file non contigui, per impostazione predefinita finiranno sugli anelli interni del piatto (s) e saranno contigui. (Voglio sottolineare che eseguo regolarmente la deframmentazione e che meno dell'1% dei miei file / directory sono frammentati), ma l'1% di 20 milioni è ancora 200K

Perché è meglio di un semplice programma di copia.

  1. Quando si esegue un programma di copia, il programma utilizzerà un meccanismo di ordinamento interno per determinare l'ordine di copia. Windows usa alfabetico (più o meno) immagino che altri facciano qualcosa di simile ma quell'ordine potrebbe - non (nel mio caso probabilmente non) conforme al modo in cui i file sono stati inizialmente posti sul disco che è quello che credo sia il più grande fattore che influisce sulla velocità di copia.

  2. Il problema con una copia di settore è che non aggiusta nulla e quindi quando eseguo la migrazione tra le dimensioni del disco e aggiungo i dati mi ritrovo con nuovi problemi da gestire.

  3. Se lo faccio correttamente dovrei essere in grado di controllare le intestazioni dei file e il record di eof e fare alcune pulizie. CHKDSK è un ottimo programma ma un po 'stupido. Quando ottengo il danneggiamento di file / cartelle è davvero difficile identificare ciò che è andato perso, creando il mio programma di copia potrei includere un ciclo di manutenzione che potrei invocare quando voglio eseguire alcuni test sui file durante la copia. Questo potrebbe rallentarlo, ma non penso molto perché la CPU sposterà i file molto più velocemente di quanto possano essere tirati o scritti. E anche se ne rallenta un po 'durante la corsa, almeno ottengo un certo controllo (forse la comprensione è una parola migliore) dei problemi che invariabilmente affioreranno in un mondo imperfetto.

Potrei non doverlo fare in A, ho cercato modi per giocare (leggere) la MFT e ci sono persino strumenti Python per questo http://www.integriography.com


Come già detto, non è la lingua qui a fare la differenza; l'assemblaggio potrebbe essere freddo o veloce per i calcoli, ma quando il processore deve "parlare" con le periferiche, il limite è dato da questi. In questo caso la velocità è data dalla velocità del tuo hard disk, e questo è un limite che difficilmente puoi cambiare senza cambiare il tuo hd e aspettando un hd migliore in futuro, ma anche dal modo in cui i dati sono organizzati sul disco, cioè dal filesystem . AFAIK, i filesystem più usati non sono ottimizzati per gestire velocemente tonnellate di file "piccoli", ma sono ottimizzati per contenere "pochi" file enormi.

Quindi, cambiare il filesystem che stai usando potrebbe aumentare la tua velocità di copia, nella misura in cui è più adatto al tuo caso (e naturalmente i limiti di hd sono ancora validi!). Se vuoi "assaggiare" il vero limite del tuo hd, dovresti provare una copia "settore per settore", rispondendo all'immagine esatta del tuo hd sorgente sul dest hd. (Ma questa opzione ha alcuni punti di cui essere a conoscenza)


RICHCOPY sta già copiando file in parallelo, e mi aspetto che l'unico modo per sconfiggerlo sia quello di mettersi a letto con il filesystem in modo da ridurre al minimo l'I / O del disco , in particolare la ricerca. Ti suggerisco di provare ntfsclone per vedere se soddisfa le tue esigenze. In caso contrario, il mio prossimo suggerimento sarebbe quello di parallelizzare ntfsclone .

In ogni caso, lavorare direttamente con il layout del filesystem su disco sarà più semplice in C, non in Python e certamente non in assembly. Soprattutto dal momento che è possibile iniziare utilizzando il codice C dal progetto NTFS 3G . Questo codice è progettato per affidabilità e facilità di porting, non di prestazioni, ma è ancora probabilmente il modo più semplice per iniziare.

Il mio tempo è abbastanza prezioso che sto cercando di capire se riuscirò a vedere guadagni abbastanza significativi in ​​termini di velocità di copia.

No. O più esattamente, al livello attuale di padronanza della programmazione dei sistemi, ottenere significativi miglioramenti della velocità sarà proibitivo . Quello che chiedi richiede competenze specialistiche. Sebbene io abbia esperienza precedente nell'implementazione di filesystem (molto più semplici di NTFS, XFS o ext2), non vorrei affrontare questo lavoro; Lo assumerei fatto.

Nota a piè di pagina: se si ha accesso a una scatola Linux, scoprire quale larghezza di banda di scrittura grezza è possibile ottenere nell'unità di destinazione:

time dd if=/dev/zero of=/dev/sdc bs=1024k count=100

ti darà il tempo di scrivere 100 MB in modo sequenziale nel modo più veloce possibile. Questo ti darà un limite assoluto su ciò che è possibile con il tuo hardware. Non provarlo senza capire la pagina man di dd ! dd sta per "distruggere i dati". (In realtà sta per "copia e converti", ma cc stato preso.)

Un programmatore di Windows può probabilmente indirizzarti a un test equivalente per Windows.


1,5 TB in circa 50 ore danno un throughput di (1,5 * 1024 ^ 2) MB / (50 * 60 ^ 2) s = 8,7 MB / s. Una larghezza di banda teorica di 100 mbit / s dovrebbe darvi 12,5 MB / s. Mi sembra che la tua connessione firewire sia un problema. Si dovrebbe guardare l'aggiornamento dei driver o l'aggiornamento a una migliore interfaccia firewire / esata / usb.

Detto questo, anziché la domanda python / assembly, dovresti cercare di acquisire una soluzione di sincronizzazione dei file. Non dovrebbe essere necessario copiare questi dati più e più volte.


Non c'è alcun motivo per scrivere un programma di copia in assembly. Il problema è con la quantità di IO coinvolti non nella CPU. Inoltre, la funzione di copia in python è già scritta in C da esperti e non ti verrai più a scrivere in assembler.

Infine, il threading non sarà di aiuto, specialmente in python. Vai con Twisted o usa semplicemente il nuovo modulo multiprocessing in Python 2.6 e avvia un gruppo di processi per fare le copie. Salva te stesso un sacco di tormenti mentre fai il lavoro.


Ci sono 2 posti per il rallentamento:

  • La copia per file è MOLTO più lenta di una copia su disco (dove si clona letteralmente il 100% dei dati di ogni settore). Soprattutto per i file da 20 mm. Non è possibile correggere quello con l'assieme più sintonizzato, a meno che non si passi dalla clonazione dei file alla clonazione dei dati del disco non elaborato. In quest'ultimo caso, sì, Assembly è davvero il tuo biglietto (o C) .

  • La semplice memorizzazione di file da 20 mm e la loro ricerca ricorsiva potrebbero essere meno efficienti in Python. Ma è più probabile che si tratti di trovare un algoritmo migliore e probabilmente non sarà migliorato in modo significativo da Assembly. Inoltre, NON sarà il principale contributore a 50 ore

In sintesi, l'assembly sarà di aiuto se si esegue una copia del settore del disco non formattata, ma NON sarà di aiuto se si esegue una copia a livello di file system.


Non penso che scriverlo in assemblea ti aiuterà. Scrivere una routine in assembly può aiutarti se sei legato al processore e pensi di poter fare qualcosa di più intelligente del tuo compilatore. Ma in una copia di rete, sarai legato all'IO, quindi radere un ciclo qua o là quasi certamente non farà la differenza.

Penso che la regola genrea qui sia che è sempre meglio definire il tuo processo per vedere dove passi il tempo prima di pensare alle ottimizzazioni.


Bene, qui il collo di bottiglia non è nell'esecuzione del software di copia ma piuttosto l'accesso al disco.

Il raggiungimento di un livello inferiore non significa che si avranno prestazioni migliori. Prendiamo un semplice esempio di API open () e fopen () dove open è molto più basso è più diretto e fopen () è un wrapper di libreria per la funzione system open ().

Ma in realtà, fopen ha prestazioni migliori perché aggiunge buffering e ottimizza molte cose che non vengono eseguite nella funzione raw open ().

L'implementazione delle ottimizzazioni a livello di assembly è molto più difficile e meno efficiente rispetto a Python.





assembly