Quali sono le migliori librerie Haskell per rendere operativo un programma? [chiuso]


115

Se ho intenzione di mettere un programma in produzione, ci sono diverse cose che devo fare per poterlo considerare "reso operativo", ovvero funzionante e gestibile in modo misurabile e verificabile sia dagli ingegneri che dal personale operativo. Per i miei scopi, un programma operazionalizzato deve:

  • Essere in grado di accedere a più livelli (es: debug, avviso, ecc.).
  • Essere in grado di raccogliere e condividere metriche / statistiche sui tipi di lavoro che il programma sta svolgendo e sulla durata del lavoro. Idealmente, le metriche raccolte sono disponibili in un formato compatibile con strumenti di monitoraggio di uso comune come Ganglia , o possono essere modificate.
  • Essere configurabile, idealmente tramite un sistema che consente di aggiornare le proprietà configurate nei programmi in esecuzione senza riavviare tali programmi.
  • Essere distribuibile su server remoti in modo ripetibile.

Nel mondo Scala esistono delle buone librerie per gestire almeno i primi tre requisiti. Esempi:

Per quanto riguarda la distribuzione, un approccio adottato nel mondo Scala è quello di raggruppare il bytecode e le librerie che compongono il proprio programma con qualcosa come assembly-sbt , quindi inviare il bundle risultante (un "fat JAR") a server remoti con uno strumento come Capistrano che esegue comandi in parallelo su SSH. Questo non è un problema che richiede strumenti specifici per la lingua, ma sono curioso di sapere se tale strumento esiste nella comunità Haskell.

Probabilmente ci sono librerie Haskell che forniscono i tratti che ho descritto sopra. Vorrei sapere quali delle librerie disponibili sono considerate "migliori"; ovvero, che sono i più maturi, ben tenuti, comunemente utilizzati nella comunità Haskell ed esemplari delle migliori pratiche Haskell.

Se ci sono altre librerie, strumenti o pratiche per rendere il codice Haskell "pronto per la produzione", mi piacerebbe sapere anche di quelli.


1
Il quarto punto può causare problemi, poiché Haskell è compilato in native. Potresti provare a compilare in modo statico, il che potrebbe o non potrebbe funzionare, ma in modo ottimale avresti un ambiente simile sul server di produzione, piuttosto che sul server di sviluppo. Cabal-dev è un ambiente sandbox, che potrebbe essere adatto per il trasferimento ad altre macchine. Anche in questo caso sarebbe necessario installare almeno le librerie di base sulla macchina di destinazione.
Masse

1
Per quanto riguarda altri strumenti e tecniche, questa domanda SO ha una panoramica: stackoverflow.com/questions/3077866/…
Don Stewart,

1
Un'altra cosa: sui sistemi * nix è possibile accedere a un'enorme quantità di statistiche di processo e metadati direttamente tramite il filesystem / proc. Quindi, se si scrivono alcune routine per analizzarle, è utile sostituire la mancanza di hook diretti nel runtime.
sclv

1
distribuire un binario è facile fintanto che si costruisce sullo stesso ambiente (se il computer ha un'architettura diversa, dovresti avere un server di staging). Quindi puoi sincronizzare nuovamente il file binario e qualsiasi file esterno. Non esiste una libreria ssh per haskell per l'esecuzione automatica dei comandi di riavvio, ma puoi usare capistrano.
Greg Weber

1
@tchrist Trascorre il resto del primo paragrafo e l'elenco puntato immediatamente dopo la parola operazionalizzata spiegandone il significato in un inglese semplice.
Will McCutchen

Risposte:


54

Questa è un'ottima domanda! Ecco un primo taglio.

Essere in grado di accedere a più livelli (es: debug, avviso, ecc.).

hslogger è facilmente il framework di registrazione più popolare.

Essere in grado di raccogliere e condividere metriche / statistiche sui tipi di lavoro che il programma sta svolgendo e sulla durata del lavoro. Idealmente, le metriche raccolte sono disponibili in un formato compatibile con strumenti di monitoraggio di uso comune come Ganglia, o possono essere modificate.

Non sono a conoscenza di strumenti di reportistica standardizzati, tuttavia, l'estrazione di report dai +RTS -sflussi (o tramite flag di output di profilazione) è stata qualcosa che ho fatto in passato.

$ ./A +RTS -s
64,952 bytes allocated in the heap
1 MB total memory in use
 %GC time       0.0%  (6.1% elapsed)
 Productivity 100.0% of total user, 0.0% of total elapsed

Puoi ottenerlo anche in un formato leggibile dalla macchina:

$ ./A +RTS -t --machine-readable

 [("bytes allocated", "64952")
 ,("num_GCs", "1")
 ,("average_bytes_used", "43784")
 ,("max_bytes_used", "43784")
 ,("num_byte_usage_samples", "1")
 ,("peak_megabytes_allocated", "1")
 ,("init_cpu_seconds", "0.00")
 ,("init_wall_seconds", "0.00")
 ,("mutator_cpu_seconds", "0.00")
 ,("mutator_wall_seconds", "0.00")
 ,("GC_cpu_seconds", "0.00")
 ,("GC_wall_seconds", "0.00")
 ]

Idealmente potresti collegarti a un runtime GHC in esecuzione su un socket e guardare queste statistiche GC in modo interattivo, ma attualmente non è semplicissimo (necessita di un binding FFI all'interfaccia "rts / Stats.h"). Puoi collegarti a un processo usandoThreadScope e monitorare il comportamento di GC e threading.

Flag simili sono disponibili per la profilazione incrementale di tempo e spazio registrato , che può essere utilizzata per il monitoraggio (ad es. Questi grafici possono essere costruiti in modo incrementale).

hpcraccoglie molte statistiche sull'esecuzione del programma, tramite il suo Tixtipo, e le persone hanno scritto strumenti per registrare in intervalli di tempo il codice in esecuzione.

Essere configurabile, idealmente tramite un sistema che consente di aggiornare le proprietà configurate nei programmi in esecuzione senza riavviare tali programmi.

Sono disponibili diversi strumenti per questo, puoi ricaricare lo stato in stile xmonad; o passare al codice hotswapping tramite plugins* pacchetti o hint. Alcuni di questi sono più sperimentali di altri.

Distribuzioni riproducibili

Galois è stato recentemente rilasciato cabal-dev, che è uno strumento per creare build riproducibili (cioè le dipendenze sono definite e controllate).


6
Il pacchetto dyre dovrebbe astrarre il ricaricamento dello stato in stile xmonad, quindi dovrebbe essere menzionato in particolare, credo. Tuttavia, lega insieme la ricompilazione e la ridistribuzione, quindi si tratta in realtà di modifiche su una macchina con l'intera toolchain. Per le ridistribuzioni remote vuoi qualcosa di più simile allo stato acido, anche se è un po 'pesante per i miei gusti. Ho questa astrazione mvar persistente che ha garanzie più deboli, ma che puoi trattare come un semplice MVar che viene magicamente popolato ad ogni lancio di un binario con gli ultimi dati che conteneva.
sclv

2
Inoltre, il nuovo EventLogframework di registrazione di GHC (utilizzando +RTS -lin fase di esecuzione) trasmette l'output a un file, che può essere visualizzato con qualsiasi strumento che legga il formato del registro eventi.
Don Stewart

2
Un programma emetterà i log dei suoi eventi, in questo modo: galois.com/~dons/tmp/A.event.log - che può essere visualizzato come - i.imgur.com/QAe6r.png . Potrei immaginare di costruire altri strumenti di monitoraggio su questo formato.
Don Stewart

2
Si noti inoltre che molti strumenti di profiling sono ottimi per i test ma non tanto per il codice di produzione. Lasciando da parte l'overhead, -prof ad esempio può essere utilizzato solo con un singolo processore.
sclv

9
  • Per quanto riguarda la configurazione, ho trovato ConfigFile utile per i miei progetti. Lo uso per tutti i miei demoni in produzione. Non si aggiorna automaticamente.
  • Uso cabal-dev per creare build riproducibili in diversi ambienti (locale, dev, collega-locale). In realtà cabal-dev è indispensabile, soprattutto per la sua capacità di supportare versioni locali con patch di librerie all'interno della directory del progetto.
  • Per quello che vale, andrei con il ricaricamento dello stato in stile xmonad. La purezza di Haskell lo rende banale; la migrazione è un problema ma lo è comunque. Ho sperimentato con hsplugins e hint per il mio IRCd e nel primo caso si è verificato un problema di runtime GHC e nel secondo un errore di segmentazione. Ho lasciato i rami su Github per il successivo post mortem: https://github.com/chrisdone/hulk

Esempio di ConfigFile:

# Default options
[DEFAULT]
hostname: localhost
# Options for the first file
[file1]
location: /usr/local
user: Fred

9

Vorrei fare eco a tutto ciò che Don ha detto e aggiungere alcuni consigli generali.

Ad esempio, due strumenti e librerie aggiuntivi che potresti prendere in considerazione:

  • QuickCheck per test basati su proprietà
  • hlint come versione estesa di-Wall

Entrambi sono mirati alla qualità del codice.

Come pratica di codifica, evita Lazy IO. Se hai bisogno di streaming IO, allora vai con una delle librerie iterate come enumerator . Se guardi Hackage vedrai librerie come http-enumerator che usano uno stile enumerator per le richieste http.

Per quanto riguarda la scelta di librerie su hackage, a volte può essere utile vedere quanti pacchetti dipendono da qualcosa. Vedi facilmente le dipendenze inverse di un pacchetto puoi usare questo sito Web, che rispecchia l'hackage:

Se la tua applicazione finisce per fare loop stretti, come un server web che gestisce molte richieste, la pigrizia può essere un problema sotto forma di perdite di spazio. Spesso si tratta di aggiungere annotazioni di rigore nei posti giusti. Profilazione, esperienza e nucleo di lettura sono le principali tecniche che conosco per combattere questo genere di cose. Il miglior riferimento per la creazione di profili che io conosca è il capitolo 25 di Real-World Haskell .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.