programma C bloccato sulla attesa di continuità durante l'esecuzione di operazioni di I / O su Mac OS X Snow Leopard

StackOverflow https://stackoverflow.com/questions/2017283

  •  19-09-2019
  •  | 
  •  

Domanda

Una linea di fondo: io sono lo sviluppatore di Redis, un database NoSQL . Una delle nuove caratteristiche che sto di attuazione è la memoria virtuale, perché Redis prende tutti i dati in memoria. Grazie alla VM Redis è in grado di trasferire gli oggetti usati raramente dalla memoria al disco, ci sono una serie di ragioni per cui questo funziona molto meglio che lasciare che il sistema operativo fare il lavoro per noi lo swapping (oggetti Redis sono costruite di tanti piccoli oggetti allocati a non contigui luoghi, quando serializzato su disco da Redis prendono 10 volte meno spazio rispetto alle pagine di memoria in cui vivono, e così via).

Ora ho un'implementazione alpha che è perfettamente funzionante su Linux, ma non così bene su Mac OS X Snow Leopard. Di tanto in tanto, mentre Redis cerca di spostare una pagina dalla memoria al disco, il processo di Redis entra nello stato di attesa di continuità per i minuti. Ero in grado di eseguire il debug di questo, ma questo avviene sia in una chiamata a fseeko() o fwrite(). Dopo minuti la chiamata restituisce finalmente e Redis continua a lavorare senza problemi a tutti:. Nessun crash

La quantità di dati trasferiti è molto piccolo, qualcosa come 256 byte. Quindi non dovrebbe essere una questione di una grande quantità di I / O eseguito.

Ma c'è un particolare interessante circa il file di scambio che è obiettivo della operazione di scrittura. Si tratta di un file di grandi dimensioni (26 GB) ha creato l'apertura di un file con fopen() e poi ampliato con ftruncate(). Infine, il file viene unlink()ed in modo che Redis continua a prendere un riferimento ad esso, ma siamo sicuri che quando il processo Redis uscirà il sistema operativo sarà davvero liberare il file di swap.

Ok che è tutto, ma io sono qui per ulteriori dettagli. E BTW si può anche trovare il codice vero e proprio nel git Redis, ma non è banale per capire in cinque minuti dato che è un sistema abbastanza complesso.

La ringrazio molto per tutto l'aiuto.

È stato utile?

Soluzione

A quanto ho capito, HFS + ha il supporto molto povero per file sparsi. Quindi può essere che il vostro articolo è innescare un ampliamento file che è in fase di inizializzazione / materializzando una grande frazione del file.

Per esempio, io so mmap'ing un nuovo file vuoto di grandi dimensioni e quindi scrivendo a pochi posizioni casuali produce un file molto grande su disco con HFS +. E 'abbastanza fastidioso perché mmap e file sparsi sono un modo estremamente conveniente di lavorare con i dati, e praticamente ogni altra piattaforma / filesystem là fuori gestisce questa grazia.

è il file di swap scritto in modo lineare? Significato ci sia sostituiamo un blocco esistente o scrivere un nuovo blocco alla fine e incrementiamo un puntatore spazio libero? Se è così, forse facendo più frequenti ftruncate più piccola chiamate per espandere il file si tradurrebbe in pause più brevi.

Per inciso, io sono curioso di sapere perchè Redis VM non usa mmap e poi basta spostare blocchi intorno nel tentativo di concentrare i blocchi caldi caldi in pagine.

Altri suggerimenti

antirez, io non sono sicuro che sarò molto aiuto dal momento che la mia esperienza di Apple è limitato al Apple ][, ma darò un colpo.

Per prima cosa è una domanda. Avrei pensato che, per la memoria virtuale, la velocità di funzionamento sarebbe una misura più importante che lo spazio su disco (soprattutto per un DB NoSQL dove la velocità è il punto, altrimenti si sarebbe utilizza SQL, no?). Ma, se il file di swap è 26G, forse no: -)

Alcune cose da provare (se possibile).

  1. Prova a isolare in realtà il problema al chiedere o scrivere. Ho difficoltà a credere a cercare potrebbe richiedere molto tempo da quando, nel peggiore dei casi, dovrebbe essere un cambiamento puntatore del buffer. Eppure, non ho scritto OSX quindi non posso essere sicuro.
  2. Provare a regolare la dimensione del file di scambio per vedere se è quello che sta causando il problema.
  3. Ti capita mai di espandere dinamicamente il file di swap (al contrario di pre-allocazione)? Se lo fai, che può essere la causa del problema.
  4. si fa a scrivere sempre a partire nel file, come si può? Può essere che la creazione di un file 26G non può effettivamente riempirlo di dati, ma, se lo si crea quindi scrivere all'ultimo byte, il sistema operativo potrebbe essere necessario azzerare i byte prima di allora (rinviando l'inizializzazione, se presente).
  5. Che cosa succede se si pre-allocare l'intero file (scrivere ogni byte) e non scollegare vero? In altre parole, lasciare il file c'è tra le esecuzioni del programma (creandolo se non esiste già, ovviamente). Poi nel codice di avvio per Redis, basta inizializzare il file (puntatori e simili). Questo può sbarazzarsi di eventuali problemi come quelli di cui al punto 4.
  6. Fai sui vari siti BSD pure. Io non sono sicuro di quanto Apple ha cambiato sotto le coperte, ma OSX è solo BSD al livello più basso (Pax anatre per la copertura).
  7. Considera anche chiedendo sui siti di Apple (se non l'avete già fatto).

Bene, questo è il mio piccolo contributo, si spera vi aiuterà. Buona fortuna con il vostro progetto.

Hai disattivato il file caching per il file? cioè fcntl (fd, F_GLOBAL_NOCACHE, 1)

Hai provato il debug con DTrace eo Instruments (sperimentale DTrace front-end di Apple)?

Esplorare leopardo con DTrace

debug Chrome su OS X

Come Linus ha detto una volta sulla mailing list Git:

"Mi rendo conto che OS X le persone hanno un tempo difficile accettarlo, ma OS X filesystem sono generalmente totale e assoluta schifezza - ancor più che Windows ".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top