Re: [Python] Python, redis e bottleneck
Il 19 dicembre 2013 01:05, Antonio Cavallo a.cava...@cavallinux.eu ha scritto:: Comunque oramai i database sono tutti piu' o meno simili come affidabilita'/velocita'/caratteristiche: e credimi MySQL e' robusto a sufficienza. Non posso che essere in *completo* disaccordo, con entrambe le affermazioni. -- © 2013 :: R K-M-S L ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/19 Pietro Battiston m...@pietrobattiston.it Si, ma non guardare le lucine… usa dtrace/kprobes/systemtap, quello che va di moda ora sul tuo os. Mi dirai tu se posso considerarmi abbastanza à la page, ma prima di chiedere un consiglio in lista ho ovviamente fatto vari controlli con iotop - ad esempio verificando che, nel parsing di 150 MB di json, Insisto, secondo me uno strumento più potente come dtrace potrebbe aiutarti, perche' ti da una visione unificata su quello che sta succedendo. Puoi prendere il tuo processo e sondare insieme cosa sta succedendo, con estrema precisione. Non e' particolarmente semplice… io mi ci perdo sempre in mezzo (e poi ora ho solo macchine pingiate, salvo il laptop, su cui non sviluppo). - la prima iterazione _è_ effettivamente più lenta, ma la differenza è inferiore al 5%, mentre quello che sto cercando di identificare è una perdita di efficienza del 30%. Che disco hai? Ciò detto, non avevo neanche menzionato questi test perché - ribadisco - se il bottleneck fosse il disco - per latenza o per banda - si vedrebbe _a maggior ragione_ nell'operazione di puro parsing del json _senza_ caricamento in redis. Invece in quel caso la CPU sta fissa sopra il 99%. Io credo che ci possa essere relazione a come e' scritto il codice. Noi abbiamo avuto problemi, per esempio, su una cosa simile. Lettura di un grosso file, che finiva in pancia a pandas, *con* il parsing delle date abilitato. Il tutto abbastanza sequenziale, e la cosa non e' che andasse bene. Poi abbiamo tirato un po' di martellate a tutto e abbiamo risolto, ma abbiamo appunto disabilitato il parsing delle date (che non serviva ed era un carico troppo alto) *e* parallelizzando la lettura e la scrittura su più' processi. Ma il problema era diverso, noi si avevano più' files e venivano da rete. -- . ..: -enrico- ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/19 Antonio Cavallo a.cava...@cavallinux.eu Per ferro cosa intendi? I dischi o il database? Io intendo i dischi… i miei db sono software, quindi poco ferroso. In effetti, io intendevo proprio le macchine. Il concetto di gestirsi macchine fisiche in casa. Redis è adatto in certi scenari ma non rimpiazza un DB (può in sempre usare un DB relazionale come nosql). Non e' che sembri una buona idea, detta così'. Cioe', se intendi che certi db relazionali (PostgreSQL) hanno anche degli storage nosql, si ok. Se invece stai in pratica dicendo usa un db relazionale denormalizzato… viene da dire, perché? Perche' una volta che: cominci ad aggiungerci la gestione degli utenti, gli accessi (con possibilita' di locking), richiedere l'auditing dei dati e tuti gli altri ammenicoli vari.. vedi che alla fine torni ai db tradizionali. Cioe', se usi MySQL, che fa notoriamente cacare, usalo normalizzato, denormalizzato, a pois, come ti pare. Tanto fa sempre cacare. Meglio sarebbe non usarlo. Il mio primo db e' stato con MySQL (lacrimuccia): lo trovavo molto veloce. Per forza… a seconda di quando hai cominciato era probabilmente un db non relazionale che faceva finta. Comunque oramai i database sono tutti piu' o meno simili come affidabilita'/velocita'/caratteristiche: e credimi MySQL e' robusto a sufficienza. Mah… probabilmente non sei familiare con le features di Postgres. Perché' *non* e' simile come caratteristiche a MySQL. Cioe', e' quasi imbarazzante confrontare il feature set di MySQL a quello di Postgres, anche solo limitandosi alle query. Se poi tiriamo in ballo questioni di gestione, post Personalmente, quando conta, e' anche decisamente più' veloce di MySQL (per vari motivi). MySQL compete (o vince) quando lo usi come un db *non* relazionale, ma bisognerebbe vedere quando su postgres usi gli store nosql. Ma poi sopratutto l'affidabilità di MySQL e' causa di imbarazzo profondissimo. Cioe'… robusto a sufficienza per il guestbook della homepage personale, si. Per il resto, fortuna che non lo mantengo io. -- . ..: -enrico- ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno gio, 19/12/2013 alle 11.14 +, enrico franchi ha scritto: 2013/12/19 Pietro Battiston m...@pietrobattiston.it [...] Io credo che ci possa essere relazione a come e' scritto il codice. OK, ragionevole dubbio. Prendi _questo_ codice: import redis import random r = redis.Redis(db=0) try: while True: r[random.random()] = random.random() except KeyboardInterrupt: r.flushdb() che gira su un vecchio Intel Core2 Duo CPU T7300, a 2 GHz, con 4 GB di RAM DDR2 a 667 MHz. - Cosa mi aspetto: che almeno una delle due CPU sia fissa al 100%. - Cosa vedo se avvio top: redis-server non è mai sopra al 45%, Python non è mai sopra al 75%. - Cosa succede se invece che TCP-IP utilizzo un socket unix: l'utilizzo di CPU da parte di Python sale (e la performance pure, e parecchio), ma rimanendo comunque sotto l'80%. - Cosa posso immaginare che stia succedendo: che ci sia una latenza tra CPU e cache, o tra una CPU e l'altra CPU, o tra le CPU e la RAM, che top non sia affidabile al 100%. - Cosa non riesco nemmeno a immaginare che stia succedendo: probabilmente varie cose, motivo per cui ho scritto in lista. - Cosa me ne frega: pura curiosità, e magari pure un indizio di quanto parallelizzare codice che utilizza in modo intensivo redis possa o meno migliorare le prestazioni in modo lineare, o se viceversa qualunque cosa mi stia facendo da bottleneck adesso si riproporrebbe anche parallelizzando, magari su più di 2 CPU. ciao Pietro ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/19 Pietro Battiston m...@pietrobattiston.it [...] Io credo che ci possa essere relazione a come e' scritto il codice. OK, ragionevole dubbio. Prendi _questo_ codice: import redis import random r = redis.Redis(db=0) try: while True: r[random.random()] = random.random() except KeyboardInterrupt: r.flushdb() che gira su un vecchio Intel Core2 Duo CPU T7300, a 2 GHz, con 4 GB di RAM DDR2 a 667 MHz. Scusa ho iniziato a leggere il thread solo ora, spero di avere tutti gli elementi per risponderti: - Cosa mi aspetto: che almeno una delle due CPU sia fissa al 100%. improbabile, sia python che redis passano parecchio tempo in kernel space per trasferire i dati l'uno all'altro - Cosa vedo se avvio top: redis-server non è mai sopra al 45%, Python non è mai sopra al 75%. direi realistico, anche se usando random() hai inficiato il test visto che su Linux random() apre /dev/urandom, quindi di nuovo un bel context switch in kernel space. - Cosa succede se invece che TCP-IP utilizzo un socket unix: l'utilizzo di CPU da parte di Python sale (e la performance pure, e parecchio), ma rimanendo comunque sotto l'80%. il tempo in kernel space diminuisce, i socket unix sono piu' efficienti (anche se tecnicamente e' meglio dire che sono estremamente piu' semplici) - Cosa posso immaginare che stia succedendo: che ci sia una latenza tra CPU e cache, o tra una CPU e l'altra CPU, o tra le CPU e la RAM, che top non sia affidabile al 100%. no no fermo, i risultati che hai sono in linea con il tuo approccio, il collo di bottiglia e' il tuo hardware nel suo insieme :) - Cosa me ne frega: pura curiosità, e magari pure un indizio di quanto parallelizzare codice che utilizza in modo intensivo redis possa o meno migliorare le prestazioni in modo lineare, o se viceversa qualunque cosa mi stia facendo da bottleneck adesso si riproporrebbe anche parallelizzando, magari su più di 2 CPU. redis e' mono thread, puoi 'parallelizzare' la parte python ma visto che l'hardware ha solo 2 cpu e hai comunque 2 processi fissi nell'equazione (python e redis) non otterresti alcun vantaggio (anzi peggioreresti) Spero di averti tolto i dubbi :) -- Roberto De Ioris http://unbit.it ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno gio, 19/12/2013 alle 13.07 +0100, Roberto De Ioris ha scritto: 2013/12/19 Pietro Battiston m...@pietrobattiston.it [...] Io credo che ci possa essere relazione a come e' scritto il codice. OK, ragionevole dubbio. Prendi _questo_ codice: import redis import random r = redis.Redis(db=0) try: while True: r[random.random()] = random.random() except KeyboardInterrupt: r.flushdb() che gira su un vecchio Intel Core2 Duo CPU T7300, a 2 GHz, con 4 GB di RAM DDR2 a 667 MHz. Scusa ho iniziato a leggere il thread solo ora, spero di avere tutti gli elementi per risponderti: [...] - Cosa posso immaginare che stia succedendo: che ci sia una latenza tra CPU e cache, o tra una CPU e l'altra CPU, o tra le CPU e la RAM, che top non sia affidabile al 100%. no no fermo, i risultati che hai sono in linea con il tuo approccio, il collo di bottiglia e' il tuo hardware nel suo insieme :) Wow. Confesso che la tua mail mi ha suggerito che forse la seguente riga di top: %Cpu(s): 41,5 us, 13,2 sy, 0,0 ni, 44,8 id, 0,2 wa, 0,0 hi, 0,4 si, 0,0 st non fosse lì per bellezza. A questo punto mi resta un dubbio: sy dovrebbe in effetti rappresentare per l'appunto il tempo speso in kernel space. Considerato che i valori sopra sommano a 100, il tempo speso nel context switching in sé sarà incluso in questo valore? In id? Spalmato tra sy e us (a seconda della direzione del context switching)? Tutto sommato irrilevante? - Cosa me ne frega: pura curiosità, e magari pure un indizio di quanto parallelizzare codice che utilizza in modo intensivo redis possa o meno migliorare le prestazioni in modo lineare, o se viceversa qualunque cosa mi stia facendo da bottleneck adesso si riproporrebbe anche parallelizzando, magari su più di 2 CPU. redis e' mono thread, puoi 'parallelizzare' la parte python ma visto che l'hardware ha solo 2 cpu e hai comunque 2 processi fissi nell'equazione (python e redis) non otterresti alcun vantaggio (anzi peggioreresti) Sento che sto per vedere la luce, ma non mi è ancora chiarissimo perché un processo python aggiuntivo, magari con niceness bassa, non potrebbe sfruttare il 60% di CPU che il processo redis non utilizza - anche eventualmente sprecandone un 10% in kernel space, e quindi girando al 50%... O in altre parole: il campo sy di top mi suggerisce che il 13% speso in kernel space sia proprio quel 26% che manca al processo python per girare al 100%, e che quindi quasi tutto il tempo in kernel space sia speso, per l'appunto, nella sua CPU. È un modo sbagliato di ragionare? Magari la risposta è la stessa di sopra - il context switching è in realtà conteggiato in id? Spero di averti tolto i dubbi :) Ci vedo già parecchio più chiaro, grazie! Pietro ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno gio, 19/12/2013 alle 13.07 +0100, Roberto De Ioris ha scritto: 2013/12/19 Pietro Battiston m...@pietrobattiston.it [...] Io credo che ci possa essere relazione a come e' scritto il codice. OK, ragionevole dubbio. Prendi _questo_ codice: import redis import random r = redis.Redis(db=0) try: while True: r[random.random()] = random.random() except KeyboardInterrupt: r.flushdb() che gira su un vecchio Intel Core2 Duo CPU T7300, a 2 GHz, con 4 GB di RAM DDR2 a 667 MHz. - Cosa posso immaginare che stia succedendo: che ci sia una latenza tra CPU e cache, o tra una CPU e l'altra CPU, o tra le CPU e la RAM, che top non sia affidabile al 100%. no no fermo, i risultati che hai sono in linea con il tuo approccio, il collo di bottiglia e' il tuo hardware nel suo insieme :) Wow. Confesso che la tua mail mi ha suggerito che forse la seguente riga di top: %Cpu(s): 41,5 us, 13,2 sy, 0,0 ni, 44,8 id, 0,2 wa, 0,0 hi, 0,4 si, 0,0 st non fosse lì per bellezza. A questo punto mi resta un dubbio: sy dovrebbe in effetti rappresentare per l'appunto il tempo speso in kernel space. Considerato che i valori sopra sommano a 100, il tempo speso nel context switching in sé sarà incluso in questo valore? In id? Spalmato tra sy e us (a seconda della direzione del context switching)? Tutto sommato irrilevante? per context switch in realta' si intende il tempo (software) impiegato dal sistema a tornare in kernel mode (e viceversa) diciamo che e' solo una piccola parte di 'sy' (che comprende anche il tempo impiegato dalla syscall stessa) ma ha comunque il suo peso nell'insieme. Se ti interessa (presumo di si) leggiti le vecchie (ora e' cambiato parecchio ed e' imho piu' complesso da capire) guide su come chiamare una syscall in assembler x86 (int 0x80). Questi frammenti di codice (sperando che siano commentati) di solito chiariscono le idee molto piu' di interi libri di teoria sui sistemi operativi. - Cosa me ne frega: pura curiosità, e magari pure un indizio di quanto parallelizzare codice che utilizza in modo intensivo redis possa o meno migliorare le prestazioni in modo lineare, o se viceversa qualunque cosa mi stia facendo da bottleneck adesso si riproporrebbe anche parallelizzando, magari su più di 2 CPU. redis e' mono thread, puoi 'parallelizzare' la parte python ma visto che l'hardware ha solo 2 cpu e hai comunque 2 processi fissi nell'equazione (python e redis) non otterresti alcun vantaggio (anzi peggioreresti) Sento che sto per vedere la luce, ma non mi è ancora chiarissimo perché un processo python aggiuntivo, magari con niceness bassa, non potrebbe sfruttare il 60% di CPU che il processo redis non utilizza - anche eventualmente sprecandone un 10% in kernel space, e quindi girando al 50%... perche' andrebbe a pesare su redis nuovamente, di fatto introducendo un'altra problematica, ovvero che redis deve gestire due stream di richieste diventando il vero collo di bottiglia. Ovviamente se cambi l'architettura in modo che uno solo legga e tutti e due processano il discorso cambia, ma non so quanto sia fattibile nel tuo caso. -- Roberto De Ioris http://unbit.it ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
On 19/12/2013 12:52, Pietro Battiston wrote: [...] OK, ragionevole dubbio. Prendi _questo_ codice: import redis import random r = redis.Redis(db=0) try: while True: r[random.random()] = random.random() except KeyboardInterrupt: r.flushdb() Consiglio: se vuoi prestazioni **non** usare API di alto livello Pythoniche. Di solito sono scritte con la convenienza in mente, senza pensare minimamente alle prestazioni. Una velocissima ricerca su google (redis batch commands) riporta: http://redis.io/topics/mass-insert [...] Ciao Manlio ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno gio, 19/12/2013 alle 14.06 +0100, Roberto De Ioris ha scritto: Il giorno gio, 19/12/2013 alle 13.07 +0100, Roberto De Ioris ha scritto: 2013/12/19 Pietro Battiston m...@pietrobattiston.it [...] Io credo che ci possa essere relazione a come e' scritto il codice. OK, ragionevole dubbio. Prendi _questo_ codice: import redis import random r = redis.Redis(db=0) try: while True: r[random.random()] = random.random() except KeyboardInterrupt: r.flushdb() che gira su un vecchio Intel Core2 Duo CPU T7300, a 2 GHz, con 4 GB di RAM DDR2 a 667 MHz. - Cosa posso immaginare che stia succedendo: che ci sia una latenza tra CPU e cache, o tra una CPU e l'altra CPU, o tra le CPU e la RAM, che top non sia affidabile al 100%. no no fermo, i risultati che hai sono in linea con il tuo approccio, il collo di bottiglia e' il tuo hardware nel suo insieme :) Wow. Confesso che la tua mail mi ha suggerito che forse la seguente riga di top: %Cpu(s): 41,5 us, 13,2 sy, 0,0 ni, 44,8 id, 0,2 wa, 0,0 hi, 0,4 si, 0,0 st non fosse lì per bellezza. A questo punto mi resta un dubbio: sy dovrebbe in effetti rappresentare per l'appunto il tempo speso in kernel space. Considerato che i valori sopra sommano a 100, il tempo speso nel context switching in sé sarà incluso in questo valore? In id? Spalmato tra sy e us (a seconda della direzione del context switching)? Tutto sommato irrilevante? per context switch in realta' si intende il tempo (software) impiegato dal sistema a tornare in kernel mode (e viceversa) diciamo che e' solo una piccola parte di 'sy' (che comprende anche il tempo impiegato dalla syscall stessa) ma ha comunque il suo peso nell'insieme. OK, perfetto. Se ti interessa (presumo di si) leggiti le vecchie (ora e' cambiato parecchio ed e' imho piu' complesso da capire) guide su come chiamare una syscall in assembler x86 (int 0x80). Questi frammenti di codice (sperando che siano commentati) di solito chiariscono le idee molto piu' di interi libri di teoria sui sistemi operativi. Uhm... dovrei darmi una rinfrescatina (notevole eufemismo) all'assembler, ma se ho tempo ci do un occhio. - Cosa me ne frega: pura curiosità, e magari pure un indizio di quanto parallelizzare codice che utilizza in modo intensivo redis possa o meno migliorare le prestazioni in modo lineare, o se viceversa qualunque cosa mi stia facendo da bottleneck adesso si riproporrebbe anche parallelizzando, magari su più di 2 CPU. redis e' mono thread, puoi 'parallelizzare' la parte python ma visto che l'hardware ha solo 2 cpu e hai comunque 2 processi fissi nell'equazione (python e redis) non otterresti alcun vantaggio (anzi peggioreresti) Sento che sto per vedere la luce, ma non mi è ancora chiarissimo perché un processo python aggiuntivo, magari con niceness bassa, non potrebbe sfruttare il 60% di CPU che il processo redis non utilizza - anche eventualmente sprecandone un 10% in kernel space, e quindi girando al 50%... perche' andrebbe a pesare su redis nuovamente, di fatto introducendo un'altra problematica, ovvero che redis deve gestire due stream di richieste diventando il vero collo di bottiglia. Già, certo. Ovviamente se cambi l'architettura in modo che uno solo legga e tutti e due processano il discorso cambia, ma non so quanto sia fattibile nel tuo caso. In realtà nel mio caso specifico il collo di bottiglia è comunque la comunicazione con Redis (dovuta a scritture più che letture), quindi no, non cambierebbe molto. Grazie mille dei chiarimenti. Pietro ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno mer, 18/12/2013 alle 00.20 +0100, Enrico Bianchi ha scritto: On 12/17/2013 04:37 PM, Pietro Battiston wrote: Ad esempio un set di dati che utilizzo è la descrizione di una rete. Quindi la struttura base è un semplice dizionario { elemento1 : [elemento53, elemento114, elemento54], elemento2 : [elemento1, elemento32], ... } Io ho bisogno di rispondere in modo più veloce possibile alla domanda a chi è collegato elementox?. In teoria ti stavo rispondendo con un Usa MongoDB elencando le motivazioni per cui tale scelta sarebbe stata conveniente per il tuo caso. Poi pero`, leggendo meglio, mi sono soffermato meglio sull'esempio che hai riportato. Da quello che ho notato praticamente definisci una relazione di tipo gerarchico tra gli elementi, ovvero sei in uno scenario completamente gestito da un database a grafi (tanto che l'esempio della descrizione di una rete e` tipico per questi database). Con queste premesse, la scelta piu` corretta e` Neo4j o OrientDB, con preferenza per il primo soprattutto per un mero discorso di diffusione (OrientDB e` piu` malleabile in quanto permette una gestione sia a grafi che a documenti che a oggetti) Sì scusa, nell'ambito delle scienze sociali abbiamo il viziaccio di chiamare rete ciò che in effetti si è sempre chiamato grafo... Trovo molto interessanti i due db che mi hai suggerito, dato che mi ricapiterà di sicuro di lavorare con grossi grafi. Ma nel caso specifico per usarli in RAM dovrei di nuovo usare tmpfs? E finché non ho bisogno di algoritmi di graph traversal (diciamo con path 1), come efficienza sono analoghi a Redis? Riguardo al salvare/ricaricare database, forse l'errore che ho fatto fin dall'inizio è stato di non utilizzare semplicemente istanze diverse del server per database diversi (e vale per Redis, immagino, come per Neo4j e OrientDB). Se poi riuscissi a capire, a prescindere da tutto ciò, perché l'operazione di riempire un database Redis da un dump json non utilizzi al 100% né CPU né disco né RAM, la mia curiosità sarebbe soddisfatta. Presumo che l'I/O non ci stia dietro, quindi le latenze sono alte (parlo ad occhio, non ho il sistema sotto mano ed e` impossibile capire con le informazioni che dai) D'accordo. Scusa la domanda forse stupida, ma così a occhio l'I/O a cui stai pensando è quello tra CPU e RAM, giusto? Pietro ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Pietro Battiston wrote: l'I/O a cui stai pensando è quello tra CPU e RAM, giusto? Spero vivamente di no, per una preoccupazione meramente semantica. -- Nicola Larosa - http://www.tekNico.net/ Where Python 2 lets you be sloppy, with its 8-bit strings that served as both data and ASCII strings, with automatic (but error prone) conversions between 8-bit strings and unicodes, in Python 3 there are only bytes and strings (i.e. unicodes), with no automatic conversion between the two. This is A Good Thing. - Barry Warsaw, https://wiki.ubuntu.com/Python/3 ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/15 A. Cavallo a.cava...@cavallinux.eu Dipende tutto dalla mole di dati. Sopra 1T? Fino a diciamo 500Gb la soluzione più semplice è un disco sdd pcie, oramai costano sotto i 1000euri e puoi usare un DB tradizionale. Hei, ma invece di mantenersi tutto sto ferro non e' tipo utile usare qualcosa di più flessibile? Redis è adatto in certi scenari ma non rimpiazza un DB (può in sempre usare un DB relazionale come nosql). Non e' che sembri una buona idea, detta così'. Cioe', se intendi che certi db relazionali (PostgreSQL) hanno anche degli storage nosql, si ok. Se invece stai in pratica dicendo usa un db relazionale denormalizzato… viene da dire, perché? Cioe', se usi MySQL, che fa notoriamente cacare, usalo normalizzato, denormalizzato, a pois, come ti pare. Tanto fa sempre cacare. Meglio sarebbe non usarlo. -- . ..: -enrico- ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/16 Enrico Bianchi enrico.bian...@ymail.com Per me stai continuando a sbagliare strumento. Redis e` un database NoSQL di tipo key value con qualche struttura di gestione semplice del dato, mentre tu parli di dizionari e JSON. Con queste premesse, e` molto piu` conviente orientarsi su di un database di dipo document store, che permettono tra l'altro la navigabilita` del documento. Sistemi adatti sono quindi MongoDB, Cassandra (un po' meno), CouchDB, OrientDB e, non ultimo PostgreSQL (il datatype JSON e` completamente navigabile). A questo punto ti consiglio di valutare e di provare uno dei sistemi che ti ho appena citato, indubbiamente saranno molto piu` adatti di Redis per quello che ti prefiggi +1 Sembra un consiglio assolutamente sensato. -- . ..: -enrico- ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/17 Pietro Battiston m...@pietrobattiston.it Ma in generale sono dati estremamente semplici - in alcuni casi ad ogni chiave è associata una breve stringa, in altri una lista di brevi stringhe, in altri un piccolo dizionario i cui valori sono brevi stringhe (insomma, tutti tipi perfettamente supportati da Redis). Ad esempio un set di dati che utilizzo è la descrizione di una rete. Quindi la struttura base è un semplice dizionario { elemento1 : [elemento53, elemento114, elemento54], elemento2 : [elemento1, elemento32], ... } Io ho bisogno di rispondere in modo più veloce possibile alla domanda a chi è collegato elementox?. Ho chiacchierato ampiamente di queste cose ad Europython. Comunque preparati a soffrire veramente tanto se i dati sono tanti, tu non ti mangi teoria dei grafi a colazione *e* hai un'ottima comprensione di tutto lo stack software che usi. Cioe', gia' la rappresentazione che scegli la sopra, intendiamoci, o Python riesce ad internare tutte quelle stringhe (e se hai facile facile 1 milione di nodi sarebbero cazzi comunque)… vuoi scoprire se due nodi sono lo stesso nodo? Un confronto che potrebbe essere fatto in un'operazione, deve invece confrontare stringhe con prefisso comune. Se poi invece di vuoler scoprire a chi e' collegato 1, vuoi scoprire se 1 e 42 sono collegati… buona fortuna! Paga O(n) per qualcosa che potrebbe essere O(1). Vedi la classica rappresentazione dei grafi in Python. Vedi anche la mia presentazione ad EP2013 per vedere come stanno le cose in memoria e il dolore che ti porti appresso a quando cominci a nestare liberalmente strutture dati. Il che si risolve in: 1) passi a teoria algebrica dei grafi e ti smanacci matrici sparse (facile -- se sei forte in algebra -- efficiente, veloce, ma non scala indefinitivamente -- a meno che tu non abbia sistemi per fare calcolo distribuito su anelli arbitrari di matrici, cosa che noi iniziammo a costruire e non finimmo realmente, e che non mi risulta esista altrove) 2) cerchi di cominciare in termini di map-reduce e hai qualcuno che ti sostiene tale infrastruttura (non vuoi davvero mettere su e tenere in piedi dei cluster) 3) ti rendi conto che map-reduce per problemi sui grafi non funziona sempre troppo bene, e guardi a qualche implementazione di Pregel… buona fortuna qui 4) provi a vedere se qualche nosql graph db funziona per le tue cose, se no provi a simularlo con qualcosa di diverso -- anche relazionale, altro che denormalizzato! -- Poi e' noto che query SQL per esprimere cose sui grafi sono un dolore veramente grosso, ma non e' che denormalizzando il dolore passa, aumenta, semmai. Veniamo al problema 2: dopo che ho fatto tutte le analisi che devo fare sul dizionario tipo quello descritto sopra, devo spostare la mia attenzione ad un altro dizionario. Diciamo che la dimensione di ognuno di questi dizionari è dell'ordine di grandezza di 1-2 GB, e di RAM disponibile, inclusa quella che uso per il sistema, ne ho 5 GB. Quindi: faccio il flush del database Redis, carico la descrizione del nuovo dizionario. Ma allora e' roba piccola piccola! Non ci sono problemi. Se poi lo passi invece che in strutture orribilmente ridondanti a qualcosa di compatto tipo una matrice sparsa, vedi che la RAM ti droppa drasticamente. Scegli le strutture dati opportune, prima di metterti in mezzo con strumenti relativamente complicati. -- . ..: -enrico- ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno mer, 18/12/2013 alle 10.23 +0100, Nicola Larosa ha scritto: Pietro Battiston wrote: l'I/O a cui stai pensando è quello tra CPU e RAM, giusto? Spero vivamente di no, per una preoccupazione meramente semantica. OK, allora preciso: sono (ragionevolmente) certo che il bottleneck non sia il disco, neanche per motivi di latenza, non solo perché il LED del disco si illumina sporadicamente, ma soprattutto perché l'operazione di decodifica dello stesso identico json _senza_ popolarne il database redis - e quindi _più_ disk intensive - utilizza la CPU al 100%, come mi aspetterei. Quindi mi verrebbe da dire che l'eventuale problema di latenza è legato unicamente all'utilizzo di Redis. Pietro ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
2013/12/18 Pietro Battiston m...@pietrobattiston.it OK, allora preciso: sono (ragionevolmente) certo che il bottleneck non sia il disco, neanche per motivi di latenza, non solo perché il LED del disco si illumina sporadicamente, ma soprattutto perché l'operazione di decodifica dello stesso identico json _senza_ popolarne il database redis - e quindi _più_ disk intensive - utilizza la CPU al 100%, come mi aspetterei. Quindi mi verrebbe da dire che l'eventuale problema di latenza è legato unicamente all'utilizzo di Redis. Si, ma non guardare le lucine… usa dtrace/kprobes/systemtap, quello che va di moda ora sul tuo os. -- . ..: -enrico- ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
enrico franchi wrote: 2013/12/15 A. Cavallo a.cava...@cavallinux.eu mailto:a.cava...@cavallinux.eu Dipende tutto dalla mole di dati. Sopra 1T? Fino a diciamo 500Gb la soluzione più semplice è un disco sdd pcie, oramai costano sotto i 1000euri e puoi usare un DB tradizionale. Hei, ma invece di mantenersi tutto sto ferro non e' tipo utile usare qualcosa di più flessibile? Per ferro cosa intendi? I dischi o il database? Redis è adatto in certi scenari ma non rimpiazza un DB (può in sempre usare un DB relazionale come nosql). Non e' che sembri una buona idea, detta così'. Cioe', se intendi che certi db relazionali (PostgreSQL) hanno anche degli storage nosql, si ok. Se invece stai in pratica dicendo usa un db relazionale denormalizzato… viene da dire, perché? Perche' una volta che: cominci ad aggiungerci la gestione degli utenti, gli accessi (con possibilita' di locking), richiedere l'auditing dei dati e tuti gli altri ammenicoli vari.. vedi che alla fine torni ai db tradizionali. Cioe', se usi MySQL, che fa notoriamente cacare, usalo normalizzato, denormalizzato, a pois, come ti pare. Tanto fa sempre cacare. Meglio sarebbe non usarlo. Il mio primo db e' stato con MySQL (lacrimuccia): lo trovavo molto veloce. Comunque oramai i database sono tutti piu' o meno simili come affidabilita'/velocita'/caratteristiche: e credimi MySQL e' robusto a sufficienza. ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno mer, 18/12/2013 alle 16.53 +, enrico franchi ha scritto: 2013/12/18 Pietro Battiston m...@pietrobattiston.it OK, allora preciso: sono (ragionevolmente) certo che il bottleneck non sia il disco, neanche per motivi di latenza, non solo perché il LED del disco si illumina sporadicamente, ma soprattutto perché l'operazione di decodifica dello stesso identico json _senza_ popolarne il database redis - e quindi _più_ disk intensive - utilizza la CPU al 100%, come mi aspetterei. Quindi mi verrebbe da dire che l'eventuale problema di latenza è legato unicamente all'utilizzo di Redis. Si, ma non guardare le lucine… usa dtrace/kprobes/systemtap, quello che va di moda ora sul tuo os. Mi dirai tu se posso considerarmi abbastanza à la page, ma prima di chiedere un consiglio in lista ho ovviamente fatto vari controlli con iotop - ad esempio verificando che, nel parsing di 150 MB di json, - durante la prima iterazione, fatta partire dopo un /sbin/sysctl vm.drop_caches=3, l'utilizzo del disco è sempre sotto il 15% (d'accordo, questo non mi dice nulla sulla latenza), - durante le successive iterazioni, come prevedibile, il disco non viene _affatto_ utilizzato, dato che il json è nella cache di sistema - eppure il fenomeno che mi ha spinto a chiedere aiuto in lista rimane tale e quale, - la prima iterazione _è_ effettivamente più lenta, ma la differenza è inferiore al 5%, mentre quello che sto cercando di identificare è una perdita di efficienza del 30%. Ciò detto, non avevo neanche menzionato questi test perché - ribadisco - se il bottleneck fosse il disco - per latenza o per banda - si vedrebbe _a maggior ragione_ nell'operazione di puro parsing del json _senza_ caricamento in redis. Invece in quel caso la CPU sta fissa sopra il 99%. Comunque pazienza eh, era solo una curiosità, capisco che non hai il sistema sotto mano, né la sfera di cristallo. ciao Pietro ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno mar, 17/12/2013 alle 00.38 +0100, Enrico Bianchi ha scritto: On 12/16/2013 01:22 PM, Pietro Battiston wrote: Nel mio scenario, se dovessi (costretto con le spalle al muro) sostituire Redis lo sostituirei con un dizionario Python, che potrebbe aumentare un po' l'efficienza, a costo però di costringermi a legare i dati ad un processo specifico. Per me stai continuando a sbagliare strumento. Redis e` un database NoSQL di tipo key value con qualche struttura di gestione semplice del dato, mentre tu parli di dizionari e JSON. Con queste premesse, e` molto piu` conviente orientarsi su di un database di dipo document store, che permettono tra l'altro la navigabilita` del documento. Sistemi adatti sono quindi MongoDB, Cassandra (un po' meno), CouchDB, OrientDB e, non ultimo PostgreSQL (il datatype JSON e` completamente navigabile). A questo punto ti consiglio di valutare e di provare uno dei sistemi che ti ho appena citato, indubbiamente saranno molto piu` adatti di Redis per quello che ti prefiggi È assolutamente verosimile che mi sfugga qualcosa. Ma io non ho _oggetti_ json. Ho scoperto cos'è un json un paio di settimane fa su Wikipedia, semplicemente perché è l'unico mezzo - secondo me imperfetto - che ho trovato per fare il dump di database Redis per ricaricarlo in seguito. Non sono stato a dare i dettagli dei dati che uso perché sono di diverse tipologie. Ma in generale sono dati estremamente semplici - in alcuni casi ad ogni chiave è associata una breve stringa, in altri una lista di brevi stringhe, in altri un piccolo dizionario i cui valori sono brevi stringhe (insomma, tutti tipi perfettamente supportati da Redis). Ad esempio un set di dati che utilizzo è la descrizione di una rete. Quindi la struttura base è un semplice dizionario { elemento1 : [elemento53, elemento114, elemento54], elemento2 : [elemento1, elemento32], ... } Io ho bisogno di rispondere in modo più veloce possibile alla domanda a chi è collegato elementox?. Quindi in particolare ho bisogno che questo dizionario sia costantemente in RAM (e siccome accedo a molti elementi, ma poche volte ad ognuno, non mi basta sapere che il caching li tiene in RAM dopo il primo accesso). Qui si chiude il problema 1. Qual'è la soluzione migliore? A me sembrava di capire Redis. Ho visto¹ che con un filesystem tempfs si può utilizzare mongoDB in RAM, e presumo che la tecnica sia adattabile a tutti gli altri DB (no)SQL che hai menzionato. Ma non mi è chiaro quale sarebbe il guadagno Veniamo al problema 2: dopo che ho fatto tutte le analisi che devo fare sul dizionario tipo quello descritto sopra, devo spostare la mia attenzione ad un altro dizionario. Diciamo che la dimensione di ognuno di questi dizionari è dell'ordine di grandezza di 1-2 GB, e di RAM disponibile, inclusa quella che uso per il sistema, ne ho 5 GB. Quindi: faccio il flush del database Redis, carico la descrizione del nuovo dizionario. Funzionare funziona, ma l'operazione di caricamento mi prende 4 minuti (e mi ha spinto, per fare economia di RAM, a scrivere il parser json incrementale a cui ho accennato in un'altra mail¹). Quindi mi domandavo semplicemente se ci fosse un modo migliore. Una soluzione ai problemi 1 e 2 dovrebbe essere qualcosa di efficiente quanto Redis ma a cui io possa dire ora voglio lavorare su questo set di dati - caricalo in memoria, ora questo set di dati non mi serve più. Ma la priorità assoluta è la velocità con i dati che ho in memoria. Se poi posso abbassare i tempi che devo aspettare per caricarli, tanto meglio. Se poi riuscissi a capire, a prescindere da tutto ciò, perché l'operazione di riempire un database Redis da un dump json non utilizzi al 100% né CPU né disco né RAM, la mia curiosità sarebbe soddisfatta. È un problema hardware di bandwidth tra RAM e CPU? È la gestione dei socket da parte del sistema (Linux, per la cronaca) che impiega la CPU per il resto del tempo? Per la cronaca: avevo detto che se utilizzo Redis tramite socket unix invece che tramite TCP-IP, l'utilizzo della CPU da parte di Python passa dal 70% circa all'80% circa... sì, ma mi sono anche accorto che alla fine per fare la stessa operazione ci mette di più! ciao Pietro ¹ http://edgystuff.tumblr.com/post/49304254688/how-to-use-mongodb-as-a-pure-in-memory-db-redis-style ² http://pietrobattiston.it/jsaone ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
On 12/17/2013 04:37 PM, Pietro Battiston wrote: Ad esempio un set di dati che utilizzo è la descrizione di una rete. Quindi la struttura base è un semplice dizionario { elemento1 : [elemento53, elemento114, elemento54], elemento2 : [elemento1, elemento32], ... } Io ho bisogno di rispondere in modo più veloce possibile alla domanda a chi è collegato elementox?. In teoria ti stavo rispondendo con un Usa MongoDB elencando le motivazioni per cui tale scelta sarebbe stata conveniente per il tuo caso. Poi pero`, leggendo meglio, mi sono soffermato meglio sull'esempio che hai riportato. Da quello che ho notato praticamente definisci una relazione di tipo gerarchico tra gli elementi, ovvero sei in uno scenario completamente gestito da un database a grafi (tanto che l'esempio della descrizione di una rete e` tipico per questi database). Con queste premesse, la scelta piu` corretta e` Neo4j o OrientDB, con preferenza per il primo soprattutto per un mero discorso di diffusione (OrientDB e` piu` malleabile in quanto permette una gestione sia a grafi che a documenti che a oggetti) Se poi riuscissi a capire, a prescindere da tutto ciò, perché l'operazione di riempire un database Redis da un dump json non utilizzi al 100% né CPU né disco né RAM, la mia curiosità sarebbe soddisfatta. Presumo che l'I/O non ci stia dietro, quindi le latenze sono alte (parlo ad occhio, non ho il sistema sotto mano ed e` impossibile capire con le informazioni che dai) Enrico ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Il giorno dom, 15/12/2013 alle 22.24 +, A. Cavallo ha scritto: Dipende tutto dalla mole di dati. Sopra 1T? Fino a diciamo 500Gb la soluzione più semplice è un disco sdd pcie, oramai costano sotto i 1000euri e puoi usare un DB tradizionale. Redis è adatto in certi scenari ma non rimpiazza un DB (può in sempre usare un DB relazionale come nosql). ?! Nel mio scenario, se dovessi (costretto con le spalle al muro) sostituire Redis lo sostituirei con un dizionario Python, che potrebbe aumentare un po' l'efficienza, a costo però di costringermi a legare i dati ad un processo specifico. Quindi se vuoi sono i dump di Redis che rimpiazzano veramente un database per me. E in questa situazione se volessi investire in hardware, comprerei più RAM (dato che gli SSD sono almeno un ordine di grandezza più lenti). (per la cronaca: se ci fosse un modo più pratico/rodato/efficiente per fare il dump e ricaricare dei singoli database json sarei interessatissimo - ma non ho trovato niente, e non ho voglia di scrivermi codice ad hoc) Vorrei solo capire dov'è il bottleneck, dato che né CPU né disco (né RAM) sono utilizzati al massimo. Ma è una curiosità intellettuale (dato che comunque la CPU è utilizzata all'80%, quindi il guadagno pratico da un'eventuale illuminazione sarebbe limitato). ciao Pietro Pietro Battiston m...@pietrobattiston.it wrote: Salve a tutti, dopo l'ultima discussione in cui sono stato invitato a verificare se ci guadagnassi veramente qualcosa a mappare con oggetti le mie tabelle SQL, mi sono reso conto... che l'SQL era semplicemente lo strumento sbagliato per me. Ed ho scoperto redis. L'unico mio problema con redis è che devo usare svariati database diversi, che non stanno tutti in memoria. Però posso caricarli quando mi servono, con redis-dump-load.¹ Qui veniamo alla domanda: per fare ciò, i database devono essere salvati su disco in formato json (e qui l'efficienza è un problema secondario, dato che lo faccio una volta sola) e ricaricati. Ricaricarli è un'operazione che mi prende parecchio tempo (nel senso che devo anche farla svariate volte). Ha certamente a che fare con il fatto che il mio computer non è una scheggia (N.B: il bottleneck non è il disco), però comunque mi stupisce che, su due core che ho, l'utilizzo (verificato con un brutale top) rimanga intorno al 80% di python + i 35% di redis. Non ho altri processi impegnino il processore in maniera significativa (tant'è che nella successiva fase di analisi dei dati, python è fisso al 100%). Ho letto che redis può essere nettamente più efficiente se si usa un socket unix invece che TCP-IP, ed in effetti provando ho notato un certo incremento di prestazioni (con il TCP-IP, le cifre erano piuttosto 70% di python + 30% di redis). Sapete dirmi se potrei fare qualcosa di più? O se dovrei arrendermi? grazie Pietro ¹ : https://github.com/p/redis-dump-load/ __ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
On 12/16/2013 01:22 PM, Pietro Battiston wrote: Nel mio scenario, se dovessi (costretto con le spalle al muro) sostituire Redis lo sostituirei con un dizionario Python, che potrebbe aumentare un po' l'efficienza, a costo però di costringermi a legare i dati ad un processo specifico. Per me stai continuando a sbagliare strumento. Redis e` un database NoSQL di tipo key value con qualche struttura di gestione semplice del dato, mentre tu parli di dizionari e JSON. Con queste premesse, e` molto piu` conviente orientarsi su di un database di dipo document store, che permettono tra l'altro la navigabilita` del documento. Sistemi adatti sono quindi MongoDB, Cassandra (un po' meno), CouchDB, OrientDB e, non ultimo PostgreSQL (il datatype JSON e` completamente navigabile). A questo punto ti consiglio di valutare e di provare uno dei sistemi che ti ho appena citato, indubbiamente saranno molto piu` adatti di Redis per quello che ti prefiggi Enrico ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python, redis e bottleneck
Dipende tutto dalla mole di dati. Sopra 1T? Fino a diciamo 500Gb la soluzione più semplice è un disco sdd pcie, oramai costano sotto i 1000euri e puoi usare un DB tradizionale. Redis è adatto in certi scenari ma non rimpiazza un DB (può in sempre usare un DB relazionale come nosql). Pietro Battiston m...@pietrobattiston.it wrote: Salve a tutti, dopo l'ultima discussione in cui sono stato invitato a verificare se ci guadagnassi veramente qualcosa a mappare con oggetti le mie tabelle SQL, mi sono reso conto... che l'SQL era semplicemente lo strumento sbagliato per me. Ed ho scoperto redis. L'unico mio problema con redis è che devo usare svariati database diversi, che non stanno tutti in memoria. Però posso caricarli quando mi servono, con redis-dump-load.¹ Qui veniamo alla domanda: per fare ciò, i database devono essere salvati su disco in formato json (e qui l'efficienza è un problema secondario, dato che lo faccio una volta sola) e ricaricati. Ricaricarli è un'operazione che mi prende parecchio tempo (nel senso che devo anche farla svariate volte). Ha certamente a che fare con il fatto che il mio computer non è una scheggia (N.B: il bottleneck non è il disco), però comunque mi stupisce che, su due core che ho, l'utilizzo (verificato con un brutale top) rimanga intorno al 80% di python + i 35% di redis. Non ho altri processi impegnino il processore in maniera significativa (tant'è che nella successiva fase di analisi dei dati, python è fisso al 100%). Ho letto che redis può essere nettamente più efficiente se si usa un socket unix invece che TCP-IP, ed in effetti provando ho notato un certo incremento di prestazioni (con il TCP-IP, le cifre erano piuttosto 70% di python + 30% di redis). Sapete dirmi se potrei fare qualcosa di più? O se dovrei arrendermi? grazie Pietro ¹ : https://github.com/p/redis-dump-load/ ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python -- Sent from my Android phone with K-9 Mail. Please excuse my brevity.___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python