2015-05-31 12 views
7

Ho un server API Scotty che costruisce una query Elasticsearch, recupera i risultati da ES e esegue il rendering del json.GHC per thread Strategia GC

In confronto ad altri server come Phoenix e Gin, sto diventando più elevato utilizzo della CPU e velocità per servire ES risposte utilizzando BloodHound ma Gin e Phoenix erano grandezze meglio di Scotty in efficienza della memoria.

Statistiche per Scotty

wrk -t30 -c100 -d30s "http://localhost:3000/filters?apid=1&hfa=true" 
Running 30s test @ http://localhost:3000/filters?apid=1&hfa=true 
    30 threads and 100 connections 
    Thread Stats Avg  Stdev  Max +/- Stdev 
    Latency 192.04ms 305.45ms 1.95s 83.06% 
    Req/Sec 133.42 118.21  1.37k 75.54% 
    68669 requests in 30.10s, 19.97MB read 
Requests/sec: 2281.51 
Transfer/sec: 679.28KB 

Queste statistiche sono sul mio Mac avendo GHC 7.10.1 installato

informazioni processore i5 2.5GHx
memoria informazioni 8GB DDR3 1600 MHz

Sono abbastanza impressionato dalla concorrenza leggera basata su thread di GHC ma l'efficienza della memoria rimane una grande preoccupazione.

Profiling utilizzo della memoria mi ha dato i seguenti statistiche

39,222,354,072 bytes allocated in the heap 
    277,239,312 bytes copied during GC 
    522,218,848 bytes maximum residency (14 sample(s)) 
     761,408 bytes maximum slop 
      1124 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  373 colls, 373 par 2.802s 0.978s  0.0026s 0.0150s 
    Gen 1  14 colls, 13 par 0.534s 0.166s  0.0119s 0.0253s 

    Parallel GC work balance: 42.38% (serial 0%, perfect 100%) 

    TASKS: 18 (1 bound, 17 peak workers (17 total), using -N4) 

    SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled) 

    INIT time 0.001s ( 0.008s elapsed) 
    MUT  time 31.425s (36.161s elapsed) 
    GC  time 3.337s ( 1.144s elapsed) 
    EXIT time 0.000s ( 0.001s elapsed) 
    Total time 34.765s (37.314s elapsed) 

    Alloc rate 1,248,117,604 bytes per MUT second 

    Productivity 90.4% of total user, 84.2% of total elapsed 

gc_alloc_block_sync: 27215 
whitehole_spin: 0 
gen[0].sync: 8919 
gen[1].sync: 30902 

Phoenix non ha mai avuto più di 150 MB, mentre la memoria Gin ha preso molto più basso.

Credo che GHC usi la strategia di mark e sweep per GC. Credo anche che sarebbe stato meglio usare la strategia GC incrementale per thread simile a Erlang VM per una migliore efficienza della memoria.

E interpretando la risposta di Don Stewart a un related question deve esserci un modo per cambiare la strategia del GC in GHC.

Ho anche notato che l'utilizzo della memoria è rimasto stabile e piuttosto basso quando il livello di concorrenza era basso, quindi penso che l'utilizzo della memoria risalga solo quando la concorrenza è piuttosto alta.

Qualsiasi idea/suggerimento per risolvere questo problema.

+0

Qual è la tua * domanda * reale? Come ridurre l'utilizzo della memoria? – MathematicalOrchid

+0

In generale si. Più nello specifico, se potessi trovare un modo per abilitare la strategia GC per thread in GHC. – user2512324

+0

Avevo l'impressione che le versioni recenti di GHC * già * facessero GC per thread, ma potrei sbagliarmi ... – MathematicalOrchid

risposta

1

http://community.haskell.org/~simonmar/papers/local-gc.pdf

Questa carta da Simon Marlow descrive per-filo cumuli locali, e sostiene che questo è stato attuato in GHC. È datato 2011. Non posso essere sicuro se questo è ciò che effettivamente fa la versione attuale di GHC (cioè, questo è entrato nella versione di rilascio di GHC, è ancora lo status quo corrente, ecc.), Ma sembra il mio il ricordo non era completamente inventato.

Vorrei anche sottolineare la sezione del manuale GHC che spiega le impostazioni che è possibile ruotare per regolare il garbage collector:

https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/runtime-control.html#rts-options-gc

In particolare, per impostazione predefinita GHC utilizza un collettore 2-spazio, ma aggiungendo l'opzione -c RTS si usa un collettore ad 1 spazio leggermente più lento, che dovrebbe consumare meno RAM. (Non sono affatto chiaro su quale generazione queste informazioni siano valide)

Ho l'impressione che Simon Marlow sia il tipo che fa la maggior parte delle cose RTS (incluso il netturbino), quindi se riesci a trovarlo su IRC, è lui a chiedere se vuoi la verità diretta ...