Esistono tecniche per rilevare le ridondanze in un flusso di modifiche a un filesystem?

6

Sto lavorando su un client di sincronizzazione file che attualmente produce un flusso di modifiche al filesystem sottostante. Questo è un flusso di eventi create / update / move / delete per ogni "target" di sincronizzazione.

Ogni evento include un ID sequenza, che fornisce informazioni sull'ordinazione degli eventi e quindi informazioni quali:

  • percorso di origine (e percorso di destinazione per gli eventi di spostamento)
  • md5 (per i file)
  • Mtime timestamp
  • tipo di evento: {crea, sposta, aggiorna, cancella}

Funziona abbastanza bene, ma spesso ci sono ridondanze. Ad esempio, uno spostamento dal percorso X al percorso Y e quindi di nuovo al percorso X verrà segnalato come due eventi:

  1. X - > Y
  2. Y - > X

Questo è chiaramente ridondante e può essere rimosso completamente dallo stream.

Esistono tecniche ben documentate per rilevare e rimuovere tali ridondanze?

Allo stesso modo, esiste un modo ben compreso ed efficiente per rilevare le ridondanze derivanti dalle eliminazioni? Ad esempio:

  1. Aggiornamento A
  2. A - > B
  3. B - > C
  4. Elimina C

Qui, le modifiche 1 - 4 potrebbero essere ridotte a Delete A .

Gli approcci informali, insieme ai documenti accademici, sarebbero i benvenuti, tenendo presente che non è raro incontrare flussi di decine di migliaia di eventi in questo caso.

Grazie mille!

Modifica

Questo problema ha un nome? Il motivo per cui sono qui è perché Google mi ha deluso, e suppongo che questo sia perché mi manca un po 'di vocabolario!

    
posta blz 23.01.2018 - 13:04
fonte

2 risposte

2

Quello che stai descrivendo è molto simile nella generazione e amp; ottimizzazione.

Una differenza è che nella copia del codice le copie non sono distruttive, mentre nella tua situazione le mosse sono distruttive degli originali. Tuttavia, credo che molti degli stessi approcci potrebbero essere adattati alla tua situazione. Quindi, indicherò alcuni di loro. L'ottimizzazione opera su una sequenza o flusso di istruzioni.

Il flusso di codice ottimizzato contiene istruzioni come

Copy X -> Y
...
Copy Y -> X

Vogliamo eliminare le copie non necessarie nel flusso di codice ottimizzato finale. Quindi un approccio è propagazione della copia . L'ottimizzazione equivale a X & Y insieme vedendo la prima copia e sostituendo Y per X in seguito per eliminare la presenza di Y. Così il codice diventa:

//Copy X -> Y  eliminated by copy elimination, by equating X & Y
...             // here verify that X is not changed so X still == Y 
Copy X -> X     // later eliminated as redundant

Un'altra ottimizzazione si chiama eliminazione del codice morto . Funziona all'indietro attraverso il flusso. Prima un elemento tardivo nel flusso genera un'istruzione la cui destinazione non viene successivamente utilizzata,

add P + Q -> X
add X + Y -> Z

(qui Z non è usato) in modo che l'istruzione sia eliminata. Ciò influenza le istruzioni precedenti che generano bersagli (X, Y) che sono stati originati dall'istruzione eliminata in quanto i loro bersagli potrebbero non essere più utilizzati. Quindi alcune istruzioni precedenti possono anche essere eliminate, e questo può funzionare a ritroso attraverso lo stream.

Queste analisi comportano il rilevamento di usi (fonti) e definizioni (obiettivi), in un algoritmo o campo chiamato analisi del flusso di dati . Probabilmente è più complesso nella generazione di codice b / c del flusso di controllo all'interno del flusso di istruzioni che deve essere preso in considerazione nell'algoritmo. Il flusso di controllo in CG è solitamente suddiviso in unità chiamate blocchi di base che sono sequenze di flusso sequenziale dall'inizio alla fine; i blocchi di base sono quindi interconnessi dalle operazioni del flusso di controllo (forcella, unione, anello). Probabilmente il flusso non ha il flusso di controllo da gestire, quindi sarebbe come eseguire la prima parte dell'analisi del flusso di dati, che avviene su un singolo blocco di base e saltare l'iterazione che calcola una procedura o un programma più grande da quei blocchi di base. Vedi anche catena di utilizzo def. .

    
risposta data 23.01.2018 - 17:43
fonte
4

Tutto ciò che devi fare è tamponare gli eventi strutturati in modo che tu possa cercarli dal percorso interessato (probabilmente destinazione e ).

Il meccanismo attuale per combinare qualsiasi coppia di eventi dipende da cosa sono quegli eventi, quindi è sufficiente codificare manualmente le ottimizzazioni desiderate.

È molto più semplice fare questo a coppie che a riconoscere in qualche modo catene di 4 eventi. Ad esempio:

  1. copia ed elimina sorgente - > spostare

    • ottieni l'evento di eliminazione, cerca altri eventi indicizzati dal percorso eliminato
    • trova uno, una copia
    • percorso di corrispondenza è la fonte della copia
    • quindi sostituiscilo con uno spostamento
  2. copia ed elimina dest - > no-op

    • come sopra, ma il percorso corrispondente è la destinazione
    • rimuovi l'evento di copia originale e il gioco è fatto
  3. sposta e un'altra mossa

    • ottieni un evento di spostamento, cerca altri eventi indicizzati dal percorso di origine
    • trova uno spostamento il cui percorso di destinazione corrisponde a
    • sostituisci move(source1,dest1)+move(dest1,source2) con move(source1,dest2)

Presumo che tu stia elaborando gli eventi in ordine sequenziale, quindi la catena di 4 eventi verrà compressa a coppie.

Probabilmente puoi trovare un buon modo per strutturarlo ed esprimerlo come un motore di regole o qualcosa del genere, ma potrebbe richiedere uno sforzo maggiore rispetto alla semplice codifica delle trasformazioni che desideri direttamente.

    
risposta data 23.01.2018 - 13:20
fonte

Leggi altre domande sui tag