gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] gawk branch, feature/docit, updated. gawk-4.1.0-4896-g2563d58c


From: Antonio Giovanni Colombo
Subject: [SCM] gawk branch, feature/docit, updated. gawk-4.1.0-4896-g2563d58c
Date: Wed, 31 Aug 2022 12:38:35 -0400 (EDT)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, feature/docit has been updated
       via  2563d58c63cba9622949454711ae95becd13dc83 (commit)
      from  7119212f73fb0e0ae5411d43a71dd830271c217d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=2563d58c63cba9622949454711ae95becd13dc83

commit 2563d58c63cba9622949454711ae95becd13dc83
Author: Antonio Giovanni Colombo <azc100@gmail.com>
Date:   Wed Aug 31 18:38:02 2022 +0200

    added translation of the pm-gawk manual

diff --git a/doc/it/ChangeLog b/doc/it/ChangeLog
index 0e38f5fd..7a771ccc 100644
--- a/doc/it/ChangeLog
+++ b/doc/it/ChangeLog
@@ -1,3 +1,9 @@
+2022-08-31         Antonio Giovanni Colombo   <azc100@gmail.com>
+
+       * README.txt: Updated.
+       * pm-gawk.texi: Added.
+       * compila_pma.sh: Added.
+
 2022-08-25         Antonio Giovanni Colombo   <azc100@gmail.com>
 
        * gawktexi.in: Updated.
diff --git a/doc/it/README.txt b/doc/it/README.txt
index 53930cfe..ad630981 100644
--- a/doc/it/README.txt
+++ b/doc/it/README.txt
@@ -4,9 +4,13 @@ del libro di Arnold GAWK: Programmare efficacemente in AWK,
 SE (e solo se) il software necessario è disponibile nel
 computer in cui si scarica la distribuzione di gawk.
 
-Se la sola cosa che interessa è avere un copia del libro
-in formato PDF, questa può semplicemente essere scaricata
-dal sito:
+È inoltre possibile generare la versione PDF del Manuale
+utente della funzionalità di Memoria Persistente (pm-gawk),
+disponibile a partire dalle versione 5.2 di Gawk.
+
+Se la sola cosa che interessa è avere una copia del libro
+GAWK e/o del manuale pm-gawk in formato PDF,
+queste possono semplicemente essere scaricate dal sito:
 
 https://sites.google.com/view/gawkdoc-it/home-page
 
@@ -24,10 +28,15 @@ Un terzo script:
 
 genera_formati.sh
 
-genera il manuale in vari formati, fra cui i formati
+genera il libro in vari formati, fra cui i formati
 testo, html e info.
 
+Per generare il Manuale Utente per la Memoria Persistente
+in gawk, è disponibile lo script:
+
+compila_pma.sh
+
 Per eventuali problemi con la traduzione italiana del
-libro Gawk, fare riferimento agli indirizzi email
-dei traduttori, inseriti all'inizio della versione PDF del
-libro stesso.
+libro Gawk e/o del Manuale pm-gawk, fare riferimento
+agli indirizzi email dei traduttori, inseriti all'inizio
+della versione PDF del libro Gawk.
diff --git a/doc/it/compila_pma.sh b/doc/it/compila_pma.sh
new file mode 100755
index 00000000..2c7e7a8a
--- /dev/null
+++ b/doc/it/compila_pma.sh
@@ -0,0 +1,11 @@
+
+#
+# builds the PDF version of the pm-gawk manual,
+# in the current directory
+#
+echo "Building the pdf version of the pm-gawk manual"
+echo "in directory:"
+pwd
+# just in case, drop previous work files
+rm -f pm-gawk.aux pm-gawk.toc pm-gawk.log
+texi2pdf  pm-gawk.texi 
diff --git a/doc/it/pm-gawk.texi b/doc/it/pm-gawk.texi
new file mode 100644
index 00000000..e9a5c6f8
--- /dev/null
+++ b/doc/it/pm-gawk.texi
@@ -0,0 +1,1610 @@
+\language=30
+\input texinfo
+@settitle Manuale utente di @pmg{}
+@documentlanguage it
+
+@c TODO:  Checklist for release:
+@c    revise all   U P D A T E   items as appropriate
+@c    check all to-do notes
+@c    remove most comments
+@c    spell check (last 2am 15 Aug 2022)
+
+@c verbatim limits:  47 rows x 75 cols, smallformat 58 x 90
+
+@macro gwk {}
+@command{gawk}
+@end macro
+
+@macro pmg {}
+pm-@gwk{}
+@end macro
+
+@set TYTL Manuale Utente per la Memoria Persistente in @gwk{}
+
+@setfilename pm-gawk.info
+@settitle @value{TYTL}
+
+@dircategory Manipolazione e creazione di testi
+@direntry
+* pm-gawk: (pm-gawk).    Versione di gawk con la Memoria Persistente.
+@end direntry
+
+@fonttextsize 11
+
+@c it seems to do no harm and possibly some good if color
+@c distinguishes internal links from URLs to outside web
+@tex
+\gdef\linkcolor{0.12 0.09 .5} % TK's attempt at subdued blue
+%\gdef\linkcolor{0.5 0.09 0.12} % Dark Red
+\gdef\urlcolor{0.5 0.09 0.12} % Dark Red
+\global\urefurlonlylinktrue
+@end tex
+
+@setchapternewpage off
+
+@copying
+@noindent
+@c UPDATE copyright info below
+Copyright @copyright{} 2022 Terence Kelly @*
+@ifnottex
+@noindent
+@email{tpkelly@@eecs.umich.edu} @*
+@email{tpkelly@@cs.princeton.edu} @*
+@email{tpkelly@@acm.org} @*
+@url{http://web.eecs.umich.edu/~tpkelly/pma/} @*
+@url{https://dl.acm.org/profile/81100523747}
+@end ifnottex
+
+@noindent
+A chiunque @`e permesso copiare, distribuire e/o modificare questo
+documento, nei termini della Licenza ``GNU Free Documentation'',
+Versione 1.3, o qualsiasi versione successiva, pubblicata dalla
+Free Software Foundation, lasciando invariate le sezioni
+``Introduzione'' e ``Storia'',
+nessun testo in copertina o nell'ultima pagina di copertina.
+Una copia della licenza è disponibile nel sito @*
+@url{https://www.gnu.org/licenses/fdl-1.3.html}
+@end copying
+
+@titlepage
+@title @value{TYTL}
+@c UPDATE date below
+@subtitle 16 agosto 2022
+@subtitle @gwk{} versione 5.2
+@subtitle @pmg{} versione 2022.08Aug.03.1659520468 (Avon 7)
+@author Terence Kelly
+@author @email{tpkelly@@eecs.umich.edu}
+@author @email{tpkelly@@cs.princeton.edu}
+@author @email{tpkelly@@acm.org}
+@author @url{http://web.eecs.umich.edu/~tpkelly/pma/}
+@author @url{https://dl.acm.org/profile/81100523747}
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@headings off
+
+@c @contents  @c no need for this in a short document
+
+@node Top
+@ifnottex
+@ifnotxml
+@ifnotdocbook
+@top  Introduzione generale
+@gwk{} 5.2 introduce la funzionalità @emph{Memoria Persistente} he può
+``ricordare'' le variabili e le funzioni definite in uno script che
+possono quindi essere utilizzate in successive esecuzioni di script @gwk{};
+ciò consente di passare variabili fra script non correlati fra loro
+senza serializzare/analizzare file di testo; è inoltre possibile
+gestire file più grossi della memoria disponibile e dei file di swap
+[del computer].  Questo manuale supplementare fornisce una descrizione
+approfondita della Memoria Persistente in @gwk{}.
+
+@insertcopying
+@end ifnotdocbook
+@end ifnotxml
+@end ifnottex
+
+@menu
+* Introduzione::
+* Per iniziare::
+* Esempi::
+* Prestazioni::
+* Integrità dei dati::
+* Ringraziamenti::
+* Installazione::
+* Debugging::
+* Storia::
+@end menu
+
+@c ==================================================================
+@node    Introduzione
+@chapter Introduzione
+
+@sp 1
+
+@c UPDATE below after official release
+GNU AWK (@gwk{}) 5.2, rilasciato nel mese di settembre 2022, introduce
+la nuova funzionalità della @emph{memoria persistente} che facilita
+la preparazione di script AWK e in certi casi ne migliora le prestazioni.
+La nuova funzionalità, chiamata ``@pmg{}'',
+può ``ricordare'' le variabili e le funzioni definite in uno script,
+che possono quindi essere utilizzate in successive esecuzioni di script @gwk{}
+e consente di passare variabili fra script non correlati fra loro
+senza serializzare/analizzare file di testo---in maniera praticamente
+trasparente. @pmg{} @emph{non} richiede presenza di memoria non-volatile
+sul computer in cui viene eseguito, e neppure altre infrastrutture
+insolite; funzione sui normali computer e sui normali sistemi operativi
+che la maggior parte delle persone sta utilizzando da decenni.
+
+@c @sp 1
+
+@c TODO:  ADR:  hyperlinks to info page below
+
+@noindent
+La documentazione principale di @gwk{}@footnote{Vedere
+@url{https://www.gnu.org/software/gawk/manual/},
+@code{man gawk} @w{ } e @w{ } @code{info gawk}.}  spiega il
+funzionamento di base della nuova funzionalità di persistenza.
+Questo manuale supplementare fornisce ulteriori dettagli,
+esempi di programmi, e uno sguardo ``sotto il coperchio'' a
+@pmg{}.  Chi abbia familiarità con @gwk{} e con gli ambienti software
+di tipo Unix, può proseguire direttamente leggendo: @*
+
+@itemize @c @w{}
+@item @ref{Per iniziare} basta scrivere solo qualche carattere in più.
+@item @ref{Esempi} mostra come @pmg{} tratta tipici script AWK.
+@item @ref{Prestazioni} riguarda efficienza, regolazione S.O. e altro.
+@item @ref{Integrità dei dati} spiega come evitare di perdere i dati.
+@item @ref{Ringraziamenti} a chi ha reso possibile @pmg{}.
+@item @ref{Installazione} spiega dove ottenere @pmg{}.
+@item @ref{Debugging} spiega come gestire eventuali errori.
+@item @ref{Storia} traccia la tecnologia che sta dietro a @pmg{}.
+@end itemize
+
+@c UPDATE:  revise above when content finalized
+
+@c @sp 1
+
+@noindent
+Si può trovare la versione più recente di questo manuale, e anche
+la ``versione del regista'', nel sito web dedicato all'allocatore
+di memoria persistente usato in @pmg{}: @*
+@center @url{http://web.eecs.umich.edu/~tpkelly/pma/}
+
+@c @sp 1
+
+La traduzione italiana più recente di questo manuale si può trovare
+in: @*
+@center @url{https://sites.google.com/view/gawkdoc-it/home-page}
+
+@c @sp 1
+
+@noindent
+Due pubblicazioni descrivono [in inglese] l'allocatore di memoria
+persistente, e le prime esperienze con un prototipo di
+@pmg{} preparato a partire da una diramazione della distribuzione
+sorgente ufficiale di @gwk{}:
+@itemize
+@item @url{https://queue.acm.org/detail.cfm?id=3534855}
+@item 
@url{http://nvmw.ucsd.edu/nvmw2022-program/nvmw2022-data/@*nvmw2022-paper35-final_version_your_extended_abstract.pdf}
+@end itemize
+
+@c @sp 1
+
+@noindent
+Sentitevi liberi di inviarmi domande, suggerimenti, e resoconti di esperienze 
a: @*
+
+@noindent
+@w{ } @w{ } @w{ } @w{ } @w{ } @w{ } @w{ } @w{ }  
@email{tpkelly@@eecs.umich.edu} @w{ } (preferito) @*
+@w{ } @w{ } @w{ } @w{ } @w{ } @w{ } @w{ } @w{ }  
@email{tpkelly@@cs.princeton.edu} @*
+@w{ } @w{ } @w{ } @w{ } @w{ } @w{ } @w{ } @w{ }  @email{tpkelly@@acm.org}
+
+@c @page
+@sp 3
+@c ==================================================================
+@node    Per iniziare
+@chapter Per iniziare
+
+@c example heaps are larger than strictly necessary so that readers
+@c who use them more extensively are less likely to exhaust memory
+
+Ecco @pmg{} in azione, partendo dal prompt (@samp{$})
+della shell @command{bash}:
+@verbatim
+        $ truncate -s 4096000 heap.pma
+        $ export GAWK_PERSIST_FILE=heap.pma
+        $ gawk 'BEGIN{un_valore = 47}'
+        $ gawk 'BEGIN{un_valore += 7; print un_valore}'
+        54
+@end verbatim
+@noindent
+Per prima cosa, il comando @command{truncate} crea un @dfn{file sparso}
+vuoto (tutto a zeri binari) in cui @pmg{} immagazzinerà le variabili
+dello script; la sua dimensione dev'essere un multiplo della dimensione
+di una pagina del sistema di paginazione (4@tie{}KB).
+Poi, il comando @command{export} imposta una variabile di ambiente
+che consente a @pmg{} di trovare il file sparso; se @gwk{} @emph{non}
+trova questa variabile d'ambiente, la memoria persistente non è
+attivata.
+Il terzo comando esegue uno script AWK di una riga che inizializza la
+variabile @code{un_valore}, la quale sarà poi salvata nel file sparso, e
+in questo modo ``sopravviverà'' al programma interpretato che l'ha
+inizializzata.
+Infine, il quarto comando invoca @pmg{} utilizzando uno script AWK
+di una riga @emph{differente} dal precedente, il quale incrementa e
+visualizza script @code{un_valore}.
+La riga di output mostra che in effetti @pmg{} ha ``ricordato''
+@code{un_valore} utilizzandolo in script differenti e non correlati
+fra loro.  (Se nel file eseguibile @gwk{} trovato nel vostro
+cammino di ricerca @env{$PATH} non è disponibile la funzionalità
+di memoria persistente, l'output dell'esempio visto sopra sarebbe
+@samp{7} invece che @samp{54}. @xref{Installazione}).  Per non usare
+la persistenza finché non lo si desideri ancora, si può impedire a
+@gwk{} di trovare il nome del file sparso, dando il comando
+@command{unset GAWK_PERSIST_FILE}.  Per ``dimenticare'' del tutto
+le variabili dello script, basta cancella il file sparso che le
+contiene.
+
+@sp 2
+
+Attivare e disattivare la memoria persistente usando i comandi
+@command{export} e @command{unset} per gestire la variabile d'ambiente
+richiede attenzione: dimenticando di usare @command{unset} quando
+non si vuole più usare la memoria persistente si possono generare errori
+e confusione.  Fortunatamente @command{bash} consente di
+passare a un programma le variabili d'ambiente più selettivamente,
+comando per comando:
+@verbatim
+        $ rm heap.pma                    # ripartire da zero
+        $ unset GAWK_PERSIST_FILE        # eliminare la variabile d'ambiente
+        $ truncate -s 4096000 heap.pma   # creare il nuovo file sparso
+
+        $ GAWK_PERSIST_FILE=heap.pma gawk 'BEGIN{un_valore = 47}'
+        $ gawk 'BEGIN{un_valore += 7; print un_valore}'
+        7
+        $ GAWK_PERSIST_FILE=heap.pma gawk 'BEGIN{un_valore += 7; print 
un_valore}'
+        54
+@end verbatim
+@noindent
+La prima invocazione di @gwk{} premette la variabile d'ambiente
+speciale nella riga di comando, prima di chiamare il comando @gwk{},
+e quindi attiva @pmg{}.  La seconda invocazione di @gwk{}, tuttavia,
+@emph{non} vede la variabile d'ambiente, e quindi non utilizza la
+variabile dello script contenuta nel file sparso.  La terza invocazione
+di @gwk{} vede la variabile d'ambiente speciale, e quindi usa la variabile
+dello script contenuta nel file sparso.
+
+Mentre la situazione è già migliorata rispetto all'uso di variabili
+d'ambiente ``generali'', il passaggio di variabili d'ambiente col
+metodo visto sopra è prolisso e rozzo.  Definire un @dfn{alias} di shell
+permette di immettere meno caratteri e di semplificare la
+visualizzazione:
+@verbatim
+        $ alias pm='GAWK_PERSIST_FILE=heap.pma'
+        $ pm gawk 'BEGIN{print ++un_valore}'
+        55
+        $ pm gawk 'BEGIN{print ++un_valore}'
+        56
+@end verbatim
+
+@c @page
+@sp 3
+@c ==================================================================
+@node    Esempi
+@chapter Esempi
+
+Il primo esempio usa @pmg{} per analizzare le parole contenute nel
+testo dei libri di Mark Twain @cite{Tom Sawyer} e @cite{Huckleberry Finn}
+[nell'originale inglese] disponibili in
+@c
+@url{https://gutenberg.org/files/74/74-0.txt}
+@c
+e
+@c
+@url{https://gutenberg.org/files/76/76-0.txt}.
+@c
+Per prima cosa, i caratteri non-alfabetici sono convertiti nel
+carattere ``a capo'' [@dfn{newline}] (in modo che ogni riga contenga al
+massimo una parola), e il testo è poi fatto diventare tutto in
+caratteri minuscoli.
+@verbatim
+        $ tr -c a-zA-Z '\n' < 74-0.txt | tr A-Z a-z > sawyer.txt
+        $ tr -c a-zA-Z '\n' < 76-0.txt | tr A-Z a-z > finn.txt
+@end verbatim
+
+È facile contare la frequenza delle parole, usando i vettori
+associativi di AWK. @pmg{} rende persistenti tali vettori, in
+modi da evitare di rileggere nuovamente tutta la raccolta di
+testi dati ogni volta che ci poniamo una nuova domanda
+(``leggi una volta, analizza felicemente da allora in poi''):
+@verbatim
+        $ truncate -s 100M twain.pma
+        $ export GAWK_PERSIST_FILE=twain.pma
+        $ gawk '{ts[$1]++}' sawyer.txt                    # crea lista parole
+        $ gawk 'BEGIN{print ts["work"], ts["play"]}'      # domanda frequenza
+        92 11
+        $ gawk 'BEGIN{print ts["necktie"], ts["knife"]}'  # domanda frequenza
+        2 27
+@end verbatim
+@noindent
+Il comando @command{truncate} genera un file sparso sufficiente a
+contenere tutti i dati che dovrebbe poi contenere, più un abbondante
+spazio ulteriore.  (Come vedremo più avanti, nel @ref{File sparsi}, non
+c'è spreco di risorse).  Il comando @command{export} assicura che le
+successive invocazioni di @gwk{} attiveranno @pmg{}.  Il primo comando
+@pmg{} immagazzina la frequenza con cui ricorrono le parole nel
+libro @cite{Tom Sawyer} nel vettore associativo @code{ts[]}.
+Poiché tale vettore è persistente, i successivi comandi @pmg{} possono
+utilizzarlo senza dover rileggere il file di input.
+
+Espandere la nostra analisi per includere un secondo libro è facile.
+Creiamo un nuovo vettore associativo @code{hf[]} con le frequenza delle
+parole contenute in @cite{Huckleberry Finn}:
+@verbatim
+        $ gawk '{hf[$1]++}' finn.txt
+@end verbatim
+@noindent
+A questo punto si può liberamente accedere ai dati relativi a
+entrambi i libri, in maniera semplice ed efficiente, senza
+dover ogni volta analizzare nuovamente la raccolta di testi
+in input:
+@verbatim
+        $ gawk 'BEGIN{print ts["river"], hf["river"]}'
+        26 142
+@end verbatim
+
+Rendendo AWK più interattivo, @pmg{} invita ad effettuare delle
+``conversazioni'' a piacere con i dati disponibili.  Se ci interessa
+vedere quali parole in @cite{Finn} sono assenti da @cite{Sawyer},
+le risposte (fra cui ``flapdoodle,'' ``yellocution,'' e
+``sockdolager'') sono facili da trovare:
+@verbatim
+        $ gawk 'BEGIN{for(w in hf) if (!(w in ts)) print w}'
+@end verbatim
+@c also: doxolojer meedyevil ridicklous dingnation gumption cavortings
+@c       phrenology [words about slavery] shakespeare camelopard ope
+@c       mesmerism sapheads disremember consekens prevarication
+@c       missionaryin cannibal nebokoodneezer sentimentering palavering
+
+Le voci riguardo alla morte di Mark Twain possono risultare essere
+esagerate.  Se egli pubblicherà nuovi libri in futuro, sarà facile
+incorporarli nella nostra analisi incrementalmente, uno alla volta.
+I benefici in termini di efficienza di un tale modo
+di procedere incrementale per alcuni compiti di AWK, come l'analisi
+di file di log, sono trattati [in inglese] in
+@url{https://queue.acm.org/detail.cfm?id=3534855} e nel saggio
+sullo stesso tema, citato là e più sotto, nella sezione
+@ref{Prestazioni}.
+@c 
@url{http://nvmw.ucsd.edu/nvmw2022-program/nvmw2022-data/nvmw2022-paper35-final_version_your_extended_abstract.pdf}.
+
+Esercizio: Lo script AWK ``Markov'' riportato a pagina 79 del libro
+di Kernighan & Pike @cite{The Practice of Programming} [disponibile
+online in inglese] genera un testo a caso, ma che ricorda quello dei
+libri di un dato autore, usando una semplice tecnica di modellazione
+statistica.  Questo script consiste di una fase di ``apprendimento''
+o ``addestramento'' seguita da una fase di emissione di output.
+Si usi @pmg{} per separare le due fasi e per consentire al modello
+statistico di aggiungere incrementalmente nuovi libri a quelli già
+presenti.
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+Il nostro secondo esempio prende in esame un altro tema, che è un
+punto di forza di AWK, l'analisi di dati.  Per semplicità creeremo
+due piccoli file contenenti dati numerici.
+@verbatim
+        $ printf '1\n2\n3\n4\n5\n' > A.dat
+        $ printf '5\n6\n7\n8\n9\n' > B.dat
+@end verbatim
+@noindent
+Uno script AWK @emph{non}-persistente può calcolare le statistiche
+sommarie di base:
+@verbatim
+        $ cat sommario_convenzionale.awk
+            1 == NR  { min = max = $1 }
+            min > $1 { min  = $1 }
+            max < $1 { max  = $1 }
+                     { sum += $1 }
+            END { print "min: " min " max: " max " media: " sum/NR }
+
+        $ gawk -f sommario_convenzionale.awk A.dat B.dat
+        min: 1 max: 9 media: 5
+@end verbatim
+
+Volendo usare @pmg{} per fare lo stesso, per prima cosa occorre
+creare un file sparso che contenga le variabili del nostro script
+AWK e dire a @pmg{} dove sono memorizzate, utilizzando la solita
+variabile d'ambiente:
+@verbatim
+        $ truncate -s 10M statistiche.pma
+        $ export GAWK_PERSIST_FILE=statistiche.pma
+@end verbatim
+@noindent
+@pmg{} richiede di modificare lo script AWK visto sopra per
+assicurarsi che le variabili @code{min} e @code{max} siano
+inizializzate una volta sola, al primo utilizzo del file sparso
+e @emph{non} ogni volta che eseguiamo lo script.  Inoltre,
+mentre variabili definite dallo script come @code{min} mantengono
+il loro valore a ogni successiva invocazione di @pmg{}, le variabili
+proprie di AWK, come @code{NR} sono inizializzate di nuovo a ogni
+invocazione di @pmg{} e quindi non possono essere usate nello
+stesso modo.  Ecco una versione dello script modificata per
+@pmg{}:
+@verbatim
+        $ cat sommario_persistente.awk
+            ! init   { min = max = $1; init = 1 }
+            min > $1 { min = $1 }
+            max < $1 { max = $1 }
+                     { sum += $1; ++n }
+            END { print "min: " min " max: " max " media: " sum/n }
+@end verbatim
+@noindent
+Si noti la regola differente nella prima riga, e l'introduzione
+della variabile @code{n} al posto di @code{NR}.  Quando viene usata
+con @pmg{}, questa nuova logica di inizializzazione supporta lo
+stesso tipo di trattamento incrementale già visto nel precedente
+scenario di analisi del testo.  Per esempio, possiamo inserire
+i nostri file in input uno alla volta:
+@verbatim
+        $ gawk -f sommario_persistente.awk A.dat
+        min: 1 max: 5 media: 3
+
+        $ gawk -f sommario_persistente.awk B.dat
+        min: 1 max: 9 media: 5
+@end verbatim
+@noindent
+Come ci aspettavamo, dopo che la seconda invocazione di @pmg{}
+ha letto il secondo file, l'output è lo stesso che si ottiene
+dallo script non-persistente, che legge entrambi i file in
+input.
+
+Esercizio: Modificare gli script AWK usati sopra per calcolare
+anche la mediana e la moda (o le mode), sia usando @gwk{} convenzionale
+che @pmg{}.  (La mediana è il valore di mezzo di una lista ordinata;
+se la lista contiene un numero pari di elementi, va calcolata la
+media dei due numeri centrali. La moda è il valore (o i valori) che
+sono presenti con maggiore frequenza in una lista).
+
+@c heaps not portable across machines, use only with same gawk executable (?)
+@c    refer to gawk docs for portability constraints on heaps
+@c can use only one heap at a time
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+Il nostro terzo e ultimo insieme di esempi mostra come @pmg{}
+consente di mantenere in un file sparso sia i dati che le
+@emph{funzioni} definite dall'utente, le quali, quindi, possono
+essere, in seguito, liberamente utilizzate in script AWK indipendenti
+fra loro.
+
+@c ADR doesn't like return in count() below
+@c TK:  it was put there for a reason:
+@c $ truncate -s 10M funzioni.pma
+@c $ export GAWK_PERSIST_FILE=funzioni.pma
+@c $ gawk 'function count(A,t) {for(i in A)t++; return t}'
+@c $ gawk 'BEGIN { a["x"] = 4; a["y"] = 5; a["z"] = 6 }'
+@c $ gawk 'BEGIN { print count(a) }'
+@c 3
+@c $ gawk 'BEGIN { delete a }'
+@c $ gawk 'BEGIN { print count(a) }'
+@c [!!blank line, not zero!!]
+@c $
+
+La sequenza di comandi che segue invoca @pmg{} per creare e poi
+utilizzare una funzione definita dall'utente.  Le successive
+invocazioni utilizzano parecchi script AWK, tra loro differenti,
+che comunicano attraverso il file sparso.  Ogni invocazione può
+aggiungere funzioni definite dall'utente e aggiungere o togliere
+dati al file sparso, a beneficio delle successive invocazioni
+di @pmg{}.
+@smallformat
+@verbatim
+        $ truncate -s 10M funzioni.pma
+        $ export GAWK_PERSIST_FILE=funzioni.pma
+        $ gawk 'function conta(A,t) {for(i in A)t++; return ""==t?0:t}'
+        $ gawk 'BEGIN { a["x"] = 4; a["y"] = 5; a["z"] = 6 }'
+        $ gawk 'BEGIN { print conta(a) }'
+        3
+        $ gawk 'BEGIN { delete a["x"] }'
+        $ gawk 'BEGIN { print conta(a) }'
+        2
+        $ gawk 'BEGIN { delete a }'
+        $ gawk 'BEGIN { print conta(a) }'
+        0
+        $ gawk 'BEGIN { for (i=0; i<47; i++) a[i]=i }'
+        $ gawk 'BEGIN { print conta(a) }'
+        47
+@end verbatim
+@end smallformat
+@noindent
+Il primo comando @pmg{} crea la funzione definita dall'utente
+@code{conta()}, che restituisce il numero di elementi in un dato
+vettore associativo; si noti che la variabile @code{t} è locale
+a @code{conta()}, e non globale [ossia vale ``0'' ad ogni
+invocazione di @code{conta()}].
+Il successivo comando @pmg{} riempie un vettore associativo
+persistente con tre elementi; non sorprende quindi che la chiamata
+a @code{conta()} nel seguente comando @pmg{} trovi questi tre
+elementi.  I due comandi @pmg{} seguenti rispettivamente cancellano
+un elemento del vettore e stampano il contatore, ora ridotto a due.
+I due comandi seguenti cancellano i restanti elementi del vettore,
+e quindi viene stampato un contatore a zero.
+Infine, gli ultimi due comandi @pmg{} riempiono il vettore con
+47 elementi, e visualizzano il contatore aggiornato.
+
+@c I could be persuaded to leave the polinomial example as an
+@c exercise, offering to send my answer to readers upon request.
+
+Il seguente script di shell invoca più volte @pmg{} per creare
+un insieme di funzioni definite dall'utente che effettuano delle
+operazioni di base su polinomi di secondo grado: calcolo del
+valore in un dato punto, calcolo del discriminante, e utilizzo
+della formula quadratica per trovare le radici.
+Dopo di questo, l'espressione @math{x^2 + x - 12} viene
+scomposta come @math{(x - 3)(x + 4)}.
+@smallformat
+@verbatim
+        #!/bin/sh
+        rm -f                    polinomi.pma
+        truncate -s 10M          polinomi.pma
+        export GAWK_PERSIST_FILE=polinomi.pma
+        gawk 'function q(x) { return a*x^2 + b*x + c }'
+        gawk 'function p(x) { return "q(" x ") = " q(x) }'
+        gawk 'BEGIN { print p(2) }'           # valuta e stampa
+        gawk 'BEGIN{ a = 1; b = 1; c = -12 }' # nuovi coefficienti
+        gawk 'BEGIN { print p(2) }'           # valuta/stampa ancora
+        gawk 'function d(s) { return s * sqrt(b^2 - 4*a*c)}'
+        gawk 'BEGIN{ print "discriminante (deve>  essere >=0): " d(1)}'
+        gawk 'function r(s) { return (-b + d(s))/(2*a)}'
+        gawk 'BEGIN{ print "root: " r( 1) "   " p(r( 1)) }'
+        gawk 'BEGIN{ print "root: " r(-1) "   " p(r(-1)) }'
+        gawk 'function abs(n) { return n >= 0 ? n : -n }'
+        gawk 'function sgn(x) { return x >= 0 ? "- " : "+ " } '
+        gawk 'function f(s) { return "(x " sgn(r(s)) abs(r(s))}'
+        gawk 'BEGIN{ print "factor: " f( 1) ")" }'
+        gawk 'BEGIN{ print "factor: " f(-1) ")" }'
+        rm -f polinomi.pma
+@end verbatim
+@end smallformat
+@noindent
+
+@c @page
+@sp 3
+@c ==================================================================
+@node    Prestazioni
+@chapter Prestazioni
+
+Questo capitolo spiega parecchi vantaggi prestazionali che si possono
+ottenere dall'implementazione della memorie persistente in @pmg{},
+mostra come una regolazione del Sistema Operativo che si sta usando
+migliori talvolta le prestazioni e presenta delle misure sperimentali
+di prestazione.  Per restare sul pratico, useremo esempi da un
+Sistema Operativo GNU/Linux---programmi di utilità GNU in ambiente
+OS Linux---ma i principi valgono anche per gli altri sistemi operativi
+moderni.
+
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+@node    Accesso in tempo costante a vettori
+@section Accesso in tempo costante a vettori
+
+@pmg{} conserva l'efficienza dell'accesso ai dati quando delle
+strutture dei dati sono create da uno script e utilizzate più
+tardi da uno script differente.
+
+Si consideri il vettore associativo usato per analizzare i libri
+di Mark Twain nel @ref{Esempi}.  Abbiamo creato i vettori @code{ts[]}
+ed @code{hf[]} leggendo i file @file{sawyer.txt} e @file{finn.txt}.
+Se @i{N} denota il volume totale di questi file, la costruzione
+del vettore associativo richiede un tempo proporzionale a
+@i{N}, ossia il ``tempo atteso è @i{O(N)}'' nel gergo dell'analisi
+asintotica.  Se @i{W} è il numero di parole differenti nei file
+di input, la dimensione dei vettori associativi sarà proporzionale
+a @i{W}, o @i{O(W)}.  L'accesso a singoli elementi di vettore
+richiede solo il tempo @emph{costante} o tempo atteso @i{O(1)}
+non @i{O(N)} o @i{O(W)}, poiché @gwk{} implementa i vettori come
+tabelle hash.
+
+@c how much larger is N than W for the Twain texts?
+@c % wc -w sawyer.txt finn.txt
+@c   77523 sawyer.txt
+@c  120864 finn.txt
+@c  198387 total
+@c % cat sawyer.txt finn.txt | sort | uniq | wc -w
+@c 10447
+@c
+@c #words is 19x larger than #uniquewords
+@c
+@c Note that the total number of English words in existence is fixed,
+@c so as the size of a corpus increases without bound, the ratio of
+@c vocabulary size to corpus size tends toward zero.
+
+Il vantaggio di prestazioni di @pmg{} nasce quando script
+differenti creano e utilizzano vettori associativi.
+Ritrovare un elemento di un vettore persistente creato da un
+precedente programma @pmg{}, come fatto più sopra in
+@c
+@verb{|BEGIN{print ts["river"], hf["river"]}|},
+@c
+richiede ancora un tempo @i{O(1)}, che è asintoticamente superiore
+alle alternative.  Ricostruire ingenuamente i vettori a partire
+dai file di input originali in ogni programma @gwk{} che accede
+ai vettori richiederebbe, naturalmente, un tempo @i{O(N)}---un
+costo molto alto, se i testi della raccolta in input sono numerosi.
+Scaricare i vettori su dei file e quindi caricarli nuovamente quando
+necessario ridurrebbe il tempo di preparazione all'accesso a
+@i{O(W)}.  Ciò può essere in pratica un miglioramento notevole.
+@i{N} è all'incirca 19 volte più ampio di @i{W} nel nostro esempio
+con la raccolta di testi di Twain.  In ogni caso, @i{O(W)} rimane
+molto più lento di @i{O(1)}, che si ottiene usando @pmg{}.
+Come vedremo nel @ref{Risultati}, la differenza non è solo teorica.
+
+L'implementazione della memoria persistente utilizzata da @pmg{}
+lo mette in grado di evitare una mole di lavoro proporzionale a
+a @i{N} o @i{W} nell'accedere agli elementi di un vettore associativo
+persistente.  Sotto il coperchio, @pmg{} immagazzina le variabili
+AWK definite in uno script, come i vettori associativi, in un
+frammento persistente di un file mappato in memoria (il file sparso).
+Quando uno script AWK utilizza un elemento in un vettore associativo,
+@pmg{} lo ricerca nella tabella hash, dalla quale a sua volta si
+accede alla memoria del file sparso.
+I moderni sistemi operativi implementano i file mappati in memoria
+in modo tale che questi accessi alla memoria richiedono una quantità
+minima di movimento di dati: solo le parti di file sparso che contengono
+i dati richiesti sono ``paginati'' e resi disponibili nella memoria
+del programma @pmg{}.  Nel caso peggiore, il file sparso non è nella
+parte di filesystem già in memoria, e quindi le pagine richieste
+devono essere effettivamente lette da disco. Le nostre
+analisi asintotiche di efficienza rimangono valide a prescindere
+dal fatto che il file sparso sia già in memoria, oppure no.
+L'intero file sparso @emph{non} è acceduto solo per poter accedere a
+un elemento di un vettore associativo persistente.
+
+La memoria persistente quindi, rende @pmg{} in grado di offrire la
+flessibilità di separare la fase di acquisizione dati dalle indagini
+vere e proprie, senza la complicazione e il tempo in più richiesti
+per serializzare e caricare le strutture dati, e senza sacrificare
+un tempo di accesso costante ai vettori associativi, il che rende
+gli script AWK comodi e produttivi.
+
+@c Further details on @pmg{}'s persistent heap are available in
+@c @url{https://queue.acm.org/detail.cfm?id=3534855}
+@c
+@c and [excessively long NVMW URL below]
+@c
+@c 
@url{http://nvmw.ucsd.edu/nvmw2022-program/nvmw2022-data/nvmw2022-paper35-final_version_your_extended_abstract.pdf}.
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+@node    Memoria virtuale e file enormi
+@section Memoria virtuale e file enormi
+
+I file piccoli raramente turbano il piacere di usare AWK, causando
+problemi di prestazioni, con o senza la memoria persistente.
+Quando la dimensione delle strutture dati interne dell'interprete
+@gwk{} si avvicina alla capacità della memoria fisica, comunque,
+per ottenere delle prestazioni accettabili occorre comprendere
+il funzionamento dei moderni sistemi operativi e talora operare
+delle regolazioni sugli stessi.  Fortunatamente @pmg{} offre nuove
+possibilità di controllo per utenti attenti alle prestazioni,
+che abbiano a che fare con grossi file di dati.  Una frase
+concisa esprime la filosofia sottesa: Evitare di paginare
+favorisce una prestazione ottimale e previene delle perplessità.
+
+I moderni sistemi operativi offrono una @dfn{memoria virtuale} che
+si propone di apparire sia maggiore della memoria fisica disponibile
+(DRAM -- che è piccola) che più veloce dei dischi fisici disponibili
+(che sono lenti).  Quando l'utilizzo di memoria di un programma si
+avvicina alla capacità massima della DRAM, il sistema della memoria
+virtuale, in maniera trasparente, @dfn{pagina} (sposta) i dati del
+programma tra la DRAM e un'@dfn{area di swap} su un disco.
+La paginazione può degradare le prestazioni in maniera
+leggera o in maniera pesante, a seconda di come viene acceduta la
+memoria del programma in esecuzione.  Accessi causali a grandi
+strutture di dati possono provocare una paginazione eccessiva e
+dei rallentamenti molto vistosi.  Sfortunatamente, le tabelle hash
+che stanno dietro ai tipici vettori associativi di AWK richiedono
+strutturalmente degli accessi casuali alla memoria, e quindi dei
+grossi vettori associativi possono essere una fonte di problemi.
+
+@c ADR comments regarding below, "SSDs alleviate much of the
+@c performance problem of hard disks vs. RAM disks."
+@c
+@c TK replies:  When a significant amount of paging to *any*
+@c conventional block storage device starts, speed plummets by orders
+@c of magnitude.  I'd wager that the difference between paging vs. not
+@c is larger than the difference between paging to SSD vs. HDD.  So
+@c while SSDs are faster than HDDs, when paging begins they won't
+@c usually make the difference between acceptable vs. unacceptable
+@c performance.
+@c
+@c If you decide to try to find out for yourself, note that on many
+@c Linux systems the notorious OOM killer terminates a process well
+@c before its anonymous-memory footprint reaches the capacity of DRAM,
+@c so it's difficult even to provoke the phenomenon of interest.  And
+@c paging anonymous memory to swap can be managed differently than
+@c paging involving a file-backed memory mapping.
+@c
+@c Bottom line:  For the large majority of purposes, gawk users
+@c would be wise to avoid paging entirely, regardless of whether
+@c the pm-gawk feature is used.
+
+La memoria persistente cambia le regola a nostro favore: il Sistema
+Operativo pagina dei dati verso il @emph{file sparso} di @pmg{}
+invece che all'area swap. Ciò non cambierà di molto le prestazioni
+se il file sparso risiede in un filesystem tradizionale, su un
+disco.  Sui sistemi di tipo Unix, tuttavia, si può creare il file
+sparso su un filesystem che risiede in memoria, come @file{/dev/shm/},
+la qual cosa elimina del tutto la paginazione a dischi esterni,
+strutturalmente più lenti.  Mettere temporaneamente il file sparso
+su un tale filesystem è un accorgimento ragionevole, con due
+avvertenze. Primo, occorre tenere a mente che i filesystem che
+risiedono in memoria DRAM cessano di esistere quando la macchina
+viene riavviata o si impianta.  In secondo luogo l'utilizzo di
+memoria di @pmg{} non può eccedere la memoria DRAM disponibile,
+se si crea il file sparso in un filesystem che risiede nella
+memoria DRAM.
+
+La regolazione dei parametri di paginazione del Sistema Operativo
+può migliorare le prestazioni se si decide di eseguire @pmg{}
+utilizzando un file sparso che risieda su un dispositivo disco
+convenzionale.  Alcuni sistemi operativi hanno delle abitudini
+malsane riguardo alle pagine in memoria modificate (``sporche'',
+ovvero diverse rispetto alle pagine corrispondenti presenti
+nell'@dfn{area di swap}).  Per esempio, il Sistema Operativo può
+scrivere le pagine di memoria ``sporche'' così
+modificate al file sparso in maniera periodica e/o quando il
+Sistema Operativo ritenga che ``troppa'' memoria sia ``sporca''.
+Tale ``zelante'' comportamento può degradare notevolmente le
+prestazioni, senza recare beneficio alcuno a @pmg{}.
+Fortunatamente alcuni Sistemi Operativi consentono di modificare i
+parametri di paginazione in modo che la riscrittura sia ``pigra'' e
+non ``zelante''.  Per Linux, vedere la discussione sui parametro
+@code{dirty_*} in
+@url{https://www.kernel.org/doc/html/latest/admin-guide/sysctl/vm.html}.
+Cambiare questi parametri può prevenire un'inutile paginazione
+``zelante'':@footnote{La maniera contorta di effettuare la modifica
+utilizzando il comando @command{tee} è spiegata in
+@url{https://askubuntu.com/questions/1098059/which-is-the-right-way-to-drop-caches-in-lubuntu}.}
+@verbatim
+        $ echo 100    | sudo tee /proc/sys/vm/dirty_background_ratio
+        $ echo 100    | sudo tee /proc/sys/vm/dirty_ratio
+        $ echo 300000 | sudo tee /proc/sys/vm/dirty_expire_centisecs
+        $ echo 50000  | sudo tee /proc/sys/vm/dirty_writeback_centisecs
+@end verbatim
+@noindent
+La regolazione dei parametri può essere di aiuto sia per @gwk{} 
non-persistente
+che per @pmg{}.  [Avviso: La regolazione del Sistema Operativo è un'arte
+occulta, potreste essere di parere diverso].
+
+@c sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
+@c
+@c sudo doesn't convey root privileges to the redirection '>' when calling 
from cmd line
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+@node    File sparsi
+@section File sparsi
+
+Per risparmiare le risorse di memoria su disco, il file usato come
+deposito da @pmg{} dovrebbe essere creato come un @dfn{file sparso}:
+un file la cui dimensione logica è maggiore dello spazio che occupa
+su disco.  I filesystem moderni supportano i file sparsi, che si
+possono facilmente definire col comando di utilità @command{truncate},
+come visto negli esempi fin qui fatti.
+
+Iniziamo col creare dapprima un file convenzionale @emph{non} sparso,
+usando il comando @command{echo}:
+@verbatim
+        $ echo ciao > denso
+        $ ls -l denso
+        -rw-rw-r--. 1 me me 5 Aug  5 23:08 denso
+        $ du -h denso
+        4.0K    denso
+@end verbatim
+@noindent
+Il comando di utilità @command{ls} ci mostra che il file @file{denso}
+è lungo cinque byte (quattro per le lettere in ``ciao'' più uno per
+il carattere di ritorno a capo).  Il comando di utilità @command{du}
+ci informa che questo file consuma 4@tie{}KB di memoria---un blocco
+su disco, lo spazio minimo occupato su disco da un file di tipo
+non sparso.  Usiamo poi il comando di utilità @command{truncate}
+per creare un file sparso logicamente enorme, e controlliamo quanto
+spazio occupa su disco:
+@verbatim
+        $ truncate -s 1T sparso
+        $ ls -l sparso
+        -rw-rw-r--. 1 me me 1099511627776 Aug  5 22:33 sparso
+        $ du -h sparso
+        0       sparso
+@end verbatim
+@noindent
+Mentre @command{ls} ci restituisce la dimensione logica del file
+che ci attendevamo (un Terabyte, o 2 elevato alla quarantesima potenza),
+il comando @command{du} ci informa che il file non occupa assolutamente
+nessuna memoria.  Il filesystem aggiungerà delle risorse di memoria
+fisica a fronte di questo file man mano che dei dati vengono scritti
+su di esso; se si va a leggere parti del file che non sono state ancora
+scritte, il risultato sono dei record a zeri binari.
+
+L'aspetto ``paghi solo quello che usi'' dello spazio occupato
+dai file sparsi assicura a chi usa @pmg{} sia la convenienza che
+il controllo.  Se il vostro filesystem supporta i file sparsi,
+utilizzateli creando dei file sparsi di dimensioni abbondanti
+per @pmg{}.  La loro dimensione logica non costa nulla e l'allocazione
+di memoria persistente da parte di @pmg{} continuerà a funzionare
+finché le risorse di memoria fisica disponibili nel filesystem
+si esauriranno.  Se, al contrario, si vuole @emph{evitare} che
+un file sparso consumi troppo spazio su disco, basta definire
+la sua dimensione iniziale a qualsiasi limite si voglia porre;
+il file sparso non utilizzerà più spazio disco di quello
+specificato.  Se si copiano dei file sparsi usando il comando
+GNU @command{cp}, esso crea per default delle copie dei file
+che sono a loro volta dei file sparsi.
+
+Se un filesystem è cifrato, può impedire la creazione di file sparsi:
+se il valore in chiaro della posizione all'interno del file è tutto
+a zeri binari il corrispondente valore cifrato sarà probabilmente
+del tutto differente!  Effettuare la cifratura a livello della
+memoria [ossia codificando il dato prima di scriverlo], invece che
+lasciarla fare al filesystem, può offrire un livello accettabile di
+sicurezza, pur consentendo al filesystem l'implementazione di
+file sparsi.
+
+Talora si potrebbe preferire un file ``normale'' (invece che un file
+sparso), per contenere le variabili e le funzioni della memoria
+persistente. Per esempio, si potrebbe voler verificare
+che l'allocazione di memoria interna di @pmg{} funzioni correttamente
+fin quando le informazioni di memoria persistente hanno riempito
+completamente l'intero file.  Il comando di utilità
+@command{fallocate} può preparare il file in questione:
+@verbatim
+        $ fallocate -l 1M megabyte
+        $ ls -l megabyte
+        -rw-rw-r--. 1 me me 1048576 Aug  5 23:18 megabyte
+        $ du -h megabyte
+        1.0M    megabyte
+@end verbatim
+@noindent
+In questo modo si ottiene il Megabyte richiesto, sia
+logicamente che fisicamente.
+
+@c UPDATE:  search for username in "ls" examples
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+@node    Persistenza rispetto a durata
+@section Persistenza rispetto a durata
+
+Senza dubbio, la regola generale più importante per ottenere delle
+buone prestazioni dai computer è, ``paga solo per ciò che
+utilizzi''.@footnote{In effetti, questa regola è largamente ignorata,
+in maniere sorprendenti.  Alcuni ben noti algoritmi, descritti in
+libri di testo, continuano la loro esecuzione ben oltre il momento
+in cui hanno calcolato tutto ciò che dovevano calcolare. @*
+@c
+Vedere @url{https://queue.acm.org/detail.cfm?id=3424304}.}
+@c
+Per applicare questa regola a @pmg{} dobbiamo distinguere due
+concetti che sono frequentemente confusi tra loro: la
+persistenza e la durata.@footnote{Recentemente il termine
+``Memoria Persistente'' è stato talora usato per indicare
+un nuovo tipo di memoria non-volatile, indirizzabile byte
+per byte---una pratica infelice, che contraddice delle sensate
+convenzioni in essere da tempo, e che causa una confusione
+ingiustificata.  Tale tipo di Memoria-Non-Volatile fornisce
+durata [e non persistenza].
+La Memoria Persistente qui descritta è invece un'astrazione
+software, che non richiede l'utilizzo di Memoria-Non-Volatile
+[hardware].
+Vedere @url{https://queue.acm.org/detail.cfm?id=3358957}.} (Un terzo
+concetto, logicamente distinto è trattato nel @ref{Integrità dei dati}.)
+
+I dati @dfn{persistenti} sopravvivono ai programmi che ne fanno uso,
+ma non durano necessariamente per sempre.  Per esempio, come spiegato
+nella pagina di manuale del comando @command{mq_overview}, le code di
+messaggi sono persistenti, perché esistono finché il sistema non viene
+spento.
+I dati @dfn{durevoli} risiedono su un mezzo fisico che mantiene il
+suo contenuto anche se non è connesso a una presa di corrente.
+Per esempio, gli hard-disk e i dischi a stato solido contengono
+dati durevoli. La confusione sorge perché la persistenza e la
+durata sono spesso correlate: i dati nei normali filesystem
+che risiedono su HDD o SSD sono tipicamente sia persistenti che
+durevoli.  La familiarità con comandi di utilità come
+@code{fsync()} ed @code{msync()} potrebbe indurre a credere che
+la durata è un sottoassieme della persistenza, ma in effetti le
+due caratteristiche sono ortogonali: i dati in un'area di swap
+sono durevoli, ma non persistenti; i dati in filesystem che
+risiedono in memoria come @file{/dev/shm/} sono persistenti,
+ma non durevoli.
+
+La durata spesso costa di più rispetto alla persistenza.
+Per questo motivo, gli utenti @pmg{} attenti alle prestazioni
+pagano il costo in più per ottenere la durata solo qualora la
+semplice persistenza non sia sufficiente.
+Due modi per evitare il costo della durata sono stati discussi
+nel @ref{Memoria virtuale e file enormi}:
+Si può porre il file sparso usata da @pmg{} in un filesystem
+che risiede nella memoria DRAM del computer, e si può inibire
+l'eccessiva riscrittura del file sparso.  Espedienti come questo
+permettono di togliere il sovraccarico della durata dal tempo
+necessario per analisi di dati effettuate in molti stadi.
+Questo vale perfino se si desidera che i file sparsi rimangano
+poi durevoli: consentono a @pmg{} di funzionare a piena velocità
+usando solo la persistenza; forzano per il file utilizzato la
+durabilità (usando i comandi @command{cp} e @command{sync} secondo
+necessità) dopo che l'output è stato prodotto, in vista della
+successiva fase di analisi, e dopo che il programma @pmg{} che
+usa il file sparso è terminato.
+
+La sperimentazione utilizzando dati creati in modo casuale aiuta a
+comprendere come la persistenza e la durata influenzano le prestazioni.
+Si può scrivere un piccolo programma in C o in AWK per generare un
+flusso di testo casuale, o si può improvvisare un generatore usando
+semplicemente la riga di comando:
+@verbatim
+        $ openssl rand --base64 1000000 | tr -c a-zA-Z '\n' > casuale.dat
+@end verbatim
+@noindent
+Modificando la dimensione degli input casuali si può, per esempio,
+trovare quando le prestazioni ``vanno sotto terra'', perché l'uso di
+memoria di @pmg{} eccede la capacità della memoria DRAM del computer
+e la paginazione ha inizio.
+
+@c TODO:
+@c virtual *machines* / cloud machines can make performance hard to measure 
repeatably
+@c    here we assume good old fashioned OS install directly on "bare metal"
+
+Le sperimentazioni richiedono un'attenzione meticolosa, specie quando
+il file sparso si trova in un filesystem che risiede nella memoria del
+computer.  Non tener conto della cache del filesystem presente nella
+memoria DRAM può facilmente fuorviare nell'interpretazione dei
+risultati e rendere inaffidabile la ripetibilità.  Fortunatamente
+il Sistema Operativo Linux ci permette di svuotare la cache del
+filesystem e quindi simulare una condizione di ``partenza a freddo''
+quale si avrebbe subito dopo una ripartenza del computer.
+In tale situazione, l'accesso ai file normali sulla memoria durevole
+avverrebbe leggendo dal dispositivo fisico, e non dalla cache in
+memoria.  Una spiegazione [in inglese] riguardo ai comandi
+@command{sync} e @file{/proc/sys/vm/drop_caches} si trova in @*
+@c
+@url{https://www.kernel.org/doc/html/latest/admin-guide/sysctl/vm.html}.
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+@node    Esperimenti
+@section Esperimenti
+
+Lo script di C-shell (@command{csh}) che segue illustra i concetti e
+implementa i suggerimenti presentati in questo capitolo.
+È servito per produrre i risultati trattati nel @ref{Risultati},
+è stato eseguito in una ventina di minuti, su un laptop non troppo recente.
+Si può tagliare/incollare lo script stesso e metterlo in un file,
+o scaricarlo da @url{http://web.eecs.umich.edu/~tpkelly/pma/}.
+
+@c TODO: post script to Web site when finalized
+
+Lo script misura le prestazioni di quattro differenti modi di
+effettuare delle indagini sulla frequenza delle parole contenute
+in una raccolta di testi.
+L'approccio ingenuo, leggere la raccolta di testi e metterla
+in un vettore associativo ad ogni esecuzione di una @dfn{query};
+scrivere una volta una rappresentazione in formato testo della
+tabella con la frequenza delle parole e caricarla all'inizio
+di ogni nuova @dfn{query}; usare l'estensione di @gwk{}
+@code{rwarray} per scaricare e in seguito ricaricare un vettore
+associativo; usare @pmg{} per mantenere un vettore associativo
+persistente.
+
+I commenti iniziali spiegano i prerequisiti.  Le righe 8--10
+gestiscono i parametri in input: la directory in cui eseguire i
+test e dove si trovano i file necessari, compreso il file sparso,
+il cronometro usato per misurare i tempi di esecuzione,
+e altre caratteristiche di prestazione, come l'uso massimo di
+memoria e la dimensione dell'input.  La dimensione di default
+dell'input richiede da parte di @pmg{} l'utilizzo di una memoria
+di quasi 3GB, che è sufficientemente grande da produrre risultati
+interessanti, e sufficientemente piccola per essere contenuta
+nella memoria DRAM del computer, evitando (sui computer in uso
+oggi) che sia necessaria la paginazione.
+Le righe 13--14 definiscono un cronometro improvvisato.
+
+Due sezioni dello script sono rilevanti se la directory di
+default in cui eseguire i test viene cambiata da un filesystem
+nella memoria del computer @file{/dev/shm/} a una directory su
+un normale filesystem che risiede su un disco esterno.
+Le righe 15--17 definiscono il meccanismo per eliminare gli
+eventuali dati presenti nella cache DRAM; le righe lines 23--30
+impostano i parametri del @dfn{kernel} che scoraggiano il
+ricorso frequente alla paginazione.
+
+Le righe 37--70 creano, compilano ed eseguono un piccolo
+programma scritto in C, che genera una raccolta di testi casuale.
+Il programma è veloce, flessibile e deterministico, ossia genera
+sempre lo stesso output casuale, se eseguito con gli stessi
+parametri.
+
+Le righe 71--100 testano i quattro differenti approcci ad AWK
+a fronte dello stesso input casuale, registrando separatamente
+il tempo di preparazione e quello di @dfn{query} del vettore associativo
+che contiene la frequenza delle parole.
+
+@c ADR suggests making shell script available on web site
+@c TK will do eventually
+
+@sp 1
+
+@c first line of C-shell script can't contain line-number comment
+
+@smallformat
+@verbatim
+#!/bin/csh -f
+# Imposta la var. d'amb. PMG al percorso dell'eseguibile pm-gawk e AWKLIBPATH  
     #   2
+#    per trovare rwarray.so                                                    
     #   3
+# Serve "sudo" per funzionare; si consideri se inserire in /etc/sudoers:       
     #   4
+#    Defaults:vostro_nome_utente    !autentica                                 
     #   5
+echo 'inizio:      ' `date` `date +%s`                                         
     #   6
+unsetenv GAWK_PERSIST_FILE  # disabilita persistenza per ora                   
     #   7
+set dir = '/dev/shm'        # dove si trova il file sparso etc.                
     #   8
+set tmr = '/usr/bin/time'   # volendo, disponibile anche "time" della shell    
     #   9
+set isz = 1073741824        # dimensione input, 1GB                            
     #  10
+# set isz = 100000000       # input piccolo per fare test veloci               
     #  11
+cd $dir   # tick/tock/tyme sotto sono timer improvvisati, errore ~2ms          
     #  12
+alias tick 'set t1 = `date +%s.%N`' ; alias tock 'set t2 = `date +%s.%N`'      
     #  13
+alias tyme '$PMG -v t1=$t1 -v t2=$t2 "BEGIN{print t2-t1}"'                     
     #  14
+alias tsync 'tick ; sync ; tock ; echo "sync time:  " `tyme`'                  
     #  15
+alias drop_caches 'echo 3 | sudo tee /proc/sys/vm/drop_caches'                 
     #  16
+alias snd 'tsync; drop_caches'                                                 
     #  17
+echo "pm-gawk:     $PMG" ; echo 'std gawk:   ' `which gawk`                    
     #  18
+echo "run dir:     $dir" ; echo 'pwd:        ' `pwd`                           
     #  19
+echo 'dir content:'      ; ls -l $dir |& $PMG '{print "             " $0}'     
     #  20
+echo 'timer:      ' $tmr ; echo 'AWKLIBPATH: ' $AWKLIBPATH                     
     #  21
+echo 'Parametri Sistema Operativo:' ; set vm = '/proc/sys/vm/dirty'            
     #  22
+sudo sh -c "echo 100     > ${vm}_background_ratio"     # rimettere questi      
     #  23
+sudo sh -c "echo 100     > ${vm}_ratio"                # parametri di 
paginazione   #  24
+sudo sh -c "echo 1080000 > ${vm}_expire_centisecs"     # ai loro valori di 
default  #  25
+sudo sh -c "echo 1080000 > ${vm}_writeback_centisecs"  # se necessario         
     #  26
+foreach d ( ${vm}_background_ratio  ${vm}_ratio \                              
     #  27
+            ${vm}_expire_centisecs  ${vm}_writeback_centisecs )                
     #  28
+    printf "             %-38s %7d\n" $d `cat $d`                              
     #  29
+end                                                                            
     #  30
+tick ; tock ; echo 'timr ovrhd: ' `tyme` 's (circa 2ms per TK)'                
     #  31
+tick ; $PMG 'BEGIN{print "pm-gawk?     yes"}'                                  
     #  32
+tock ; echo 'pmg ovrhd:  ' `tyme` 's (circa 4-5 ms per TK)'                    
     #  33
+set inp = 'input.dat'                                                          
     #  34
+echo 'input dime. ' $isz                                                       
     #  35
+echo "input file:  $inp"                                                       
     #  36
+set rg = rgen  # crea e compila programma C per generare input casuali         
     #  37
+rm -f $inp  $rg.c $rg                                                          
     #  38
+cat <<EOF > $rg.c                                                              
     #  39
+// genera N parole casuali, una per riga, nessuna riga bianca                  
     #  40
+// caratteri sono e.g. 'abcdefg@' dove '@' diventa 'a capo'                    
     #  41
+#include <stdio.h>                                                             
     #  42
+#include <stdlib.h>                                                            
     #  43
+#include <string.h>                                                            
     #  44
+#define RCH     c = a[rand() % L];                                             
     #  45
+#define PICK    do { RCH } while (0)                                           
     #  46
+#define PICKCH  do { RCH } while (c == '@')                                    
     #  47
+#define FP(...) fprintf(stderr, __VA_ARGS__)                                   
     #  48
+int main(int argc, char *argv[]) {                                             
     #  49
+  if (4 != argc) {                                                             
     #  50
+    FP("usage:  %s  charset  N  seed\n",                                       
     #  51
+                    argv[0]);   return 1; }                                    
     #  52
+  char c, *a =      argv[1];    size_t L = strlen(a);                          
     #  53
+  long int N = atol(argv[2]);                                                  
     #  54
+  srand(       atol(argv[3]));                                                 
     #  55
+  if (2 > N) { FP("N == %ld < 2\n", N); return 2; }                            
     #  56
+  PICKCH;                                                                      
     #  57
+  for (;;) {                                                                   
     #  58
+    if (2 == N) { PICKCH; putchar(c); putchar('\n'); break; }                  
     #  59
+    if ('@' == c) { putchar('\n'); PICKCH; }                                   
     #  60
+    else          { putchar( c  ); PICK;   }                                   
     #  61
+    if (0 >= --N) break;                                                       
     #  62
+  }                                                                            
     #  63
+}                                                                              
     #  64
+EOF                                                                            
     #  65
+gcc -std=c11 -Wall -Wextra -O3 -o $rg $rg.c                                    
     #  66
+set t = '@@@@@@@' ; set c = "abcdefghijklmnopqrstuvwxyz$t$t$t$t$t$t"           
     #  67
+tick ; ./$rg "$c" $isz 47 > $inp ; tock ; echo 'gen time:   ' `tyme`           
     #  68
+echo "input file:  $inp"                                                       
     #  69
+echo 'input wc:   ' `wc < $inp` ; echo 'input uniq: ' `sort -u $inp | wc`      
     #  70
+snd 
############################################################################    
#  71
+tick ; $tmr $PMG '{n[$1]++}END{print "output: " n["foo"]}' $inp                
     #  72
+tock ; echo 'T ingenuo O(N):          ' `tyme` ; echo ''                       
     #  73
+rm -f rwa                                                                      
     #  74
+snd 
############################################################################    
#  75
+echo ''                                                                        
     #  76
+tick ; $tmr $PMG -l rwarray '{n[$1]++}END{print "writea",writea("rwa",n)}' 
$inp     #  77
+tock ; echo 'T rwarray prepara O(N):  ' `tyme` ; echo ''                       
     #  78
+snd  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
#    #  79
+tick ; $tmr $PMG -l rwarray 'BEGIN{print "reada",reada("rwa",n); \             
     #  80
+                                   print "output: " n["foo"]}'                 
     #  81
+tock ; echo 'T rwarray query O(W):   ' `tyme` ; echo ''                        
     #  82
+rm -f ft                                                                       
     #  83
+snd 
############################################################################    
#  84
+tick ; $tmr $PMG '{n[$1]++}END{for(w in n)print n[w], w}' $inp > ft            
     #  85
+tock ; echo 'T freqtbl prepara O(N):  ' `tyme` ; echo ''                       
     #  86
+snd  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
#    #  87
+tick ; $tmr $PMG '{n[$2] = $1}END{print "output: " n["foo"]}' ft               
     #  88
+tock ; echo 'T freqtbl query O(W):   ' `tyme` ; echo ''                        
     #  89
+rm -f heap.pma                                                                 
     #  90
+snd 
############################################################################    
#  91
+truncate -s 3G heap.pma  # allargare se serve                                  
     #  92
+setenv GAWK_PERSIST_FILE heap.pma                                              
     #  93
+tick ; $tmr $PMG '{n[$1]++}' $inp                                              
     #  94
+tock ; echo 'T pm-gawk prepara O(N):  ' `tyme` ; echo ''                       
     #  95
+snd  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
#    #  96
+tick ; $tmr $PMG 'BEGIN{print "output: " n["foo"]}'                            
     #  97
+tock ; echo 'T pm-gawk query O(1):    ' `tyme` ; echo ''                       
     #  98
+unsetenv GAWK_PERSIST_FILE                                                     
     #  99
+snd 
############################################################################    
# 100
+echo 'Nota:  tutte le righe di output sopra dovrebbero essere identiche' ; 
echo ''  # 101
+echo 'contenuto dir:' ; ls -l $dir |& $PMG '{print "              " $0}'       
     # 102
+echo '' ; echo 'memoria usata:'                                                
     # 103
+foreach f ( rwa ft heap.pma )  # compressione molto lenta, la omettiamo        
     # 104
+    echo "    $f " `du -BK $dir/$f` # `xz --best < $dir/$f | wc -c` 'bytes xz' 
     # 105
+end                                                                            
     # 106
+echo '' ; echo 'fine:       ' `date` `date +%s` ; echo ''                      
     # 107
+@end verbatim
+@end smallformat
+
+@c @page
+@sp 3
+@c  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+@node    Risultati
+@section Risultati
+
+Eseguendo lo script nel @ref{Esperimenti} con i parametri di default
+in un laptop non troppo recente ha dato i risultati riassunti nella
+tabella che segue.  Esperimenti più ampi, non riferiti qui, conducono
+a risultati qualitativamente simili.  Occorre tenere presente che le
+misurazioni di prestazione sono spesso influenzate da fattori
+apparentemente irrilevanti.  Per esempio, il programma in esecuzione
+può avere il vantaggio di una CPU raffreddata meglio; ulteriori
+esecuzioni possono essere effettuati con una CPU più calda, e di
+conseguenza subire gli effetti delle variazioni di @dfn{clock}
+messe in atto dall'apparato di regolazione termica di un moderno
+processore.  Molto più in generale, le misurazioni di prestazione
+sono faccende delicate.  Se si eseguono degli script, per i quali
+la facilità di preparazione prevale sulla necessità di esecuzione
+veloce, la funzione propria delle misurazioni di prestazione è
+quella di testare qualitativamente delle ipotesi come quelle
+derivanti da un'analisi asintotica, e di fornire un'idea approssimata
+di quando i vari approcci possibili siano preferibili in pratica.
+
+@page
+@verbatim
+                           tempo es.     massimo uso         memoria
+        AWK script             (sec)     memoria (K)  intermedia (K)
+
+        ingenuo       O(N)   242,132       2.081.360           n/a
+        rwarray prep. O(N)   250,288       2.846.868         156.832
+        rwarray query O(W)    11,653       2.081.444
+        freqtbl prep. O(N)   288,408       2.400.120          69.112
+        freqtbl query O(W)    11,624       2.336.616
+        pm-gawk prep. O(N)   251,946       2.079.520       2.076.608
+        pm-gawk query O(1)     0,026           3.252
+@end verbatim
+
+@sp 1
+
+I risultati sono consistenti con l'analisi asintotica nel
+@ref{Accesso in tempo costante a vettori}.  Tutti e quattro gli approcci
+richiedono circa quattro minuti per la lettura dei dati in input.
+L'approccio ingenuo deve farlo ogni volta che si effettua una
+@dfn{query}, ma gli altri tre approcci costruiscono un unico vettore
+associativo, usato per ognuna delle successive @dfn{query}.
+Gli approcci @code{freqtbl} ed @code{rwarray} costruiscono un vettore
+associativo di parole, lo scaricano su un file intermedio, che
+rileggono prima di ogni @dfn{query}; il primo dei due lo fa manualmente
+mentre l'altro usa un'estensione @gwk{}.  Entrambi possono eseguire
+una nuova @dfn{query} in una decina di secondi, non in quattro minuti.
+Come previsto dall'analisi asintotica, eseguire un lavoro in un tempo
+proporzionale al numero di parole nel vettore è preferibile a eseguire
+il lavoro in un tempo proporzionale alla dimensione della raccolta di
+testi in input: il tempo @i{O(W)} è minore di @i{O(N)}.
+E, sempre come previsto, le @dfn{query} di @pmg{}'s a tempo costante
+sono ancor più veloci, all'incirca di un paio di ordini di grandezza.
+Per i calcoli qui presi in esame, @pmg{} fa la differenza fra un
+batter d'occhio e un tempo di risposta sufficientemente lungo perché
+la mente dell'utente cominci a pensare ad altro.
+
+Mentre @code{freqtbl} ed @code{rwarray} ricostruiscono un vettore
+associativo, prima di accedere a un elemento dello stesso,
+@pmg{} immagazzina nella memoria persistente un vettore associativo
+pronto per l'uso.  Questo è il motivo per cui il suo file intermedio
+(il file sparso) è molto più grande degli altri due file intermedi,
+e la ragione per cui il file sparso è quasi grande quanto il massimo
+uso di memoria da parte di @pmg{} nella fase di preparazione del
+vettore associativo, mentre l'uso di memoria è molto piccolo quando
+usato da una @dfn{query} che accede a un singolo elemento del
+vettore.
+Il vantaggio che deriva dall'avere un file sparso grande è il
+tempo di accesso @i{O(1)} invece che @i{O(W)}---un classico
+compromesso fra tempo e spazio.  Se la memoria su disco è una
+risorsa scarsa, tutti e tre i file intermedi possono essere compressi,
+quello @code{freqtbl} di un fattore all'incirca 2,7x, @code{rwarray}
+all'incirca 5,6x, e @pmg{} all'incirca 11x, usando il comando
+@command{xz}.  La compressione usa molto la memoria ed è lenta, un
+altro compromesso fra tempo e spazio.
+
+@c @page
+@sp 3
+@c ==================================================================
+@node    Integrità dei dati
+@chapter Integrità dei dati
+
+Contrattempi come le mancanze di corrente, gli errori del @dfn{kernel},
+i bug negli script, e i refusi sulla riga-dei-comandi possono causare
+danni ai vostri dati, ma ci sono delle precauzioni che servono a
+diminuire questi rischi.  Negli scenari che prevedono l'uso di script
+basta di solito creare un backup dei file importanti, in tempi
+appropriati.  Per quanto semplice questo sembri, è necessario
+prestare attenzione per ottenere una protezione genuina e per
+ridurre il costo del backup.  Quel che segue è una maniera prudente
+e poco costosa di creare un backup del file sparso fra un uso e
+l'altro:
+@verbatim
+        $ nome_backup=sparso_bkup`date +%s`
+        $ cp --reflink=always sparso.pma $nome_backup.pma
+        $ chmod a-w $nome_backup.pma
+        $ sync
+        $ touch $nome_backup.fatto
+        $ chmod a-w $nome_backup.fatto
+        $ sync
+        $ ls -l sparso*
+        -rw-rw-r--. 1 me me 4096000 Aug  6 15:53 sparso.pma
+        -r--r--r--. 1 me me       0 Aug  6 16:16 sparso_bkup1659827771.fatto
+        -r--r--r--. 1 me me 4096000 Aug  6 16:16 sparso_bkup1659827771.pma
+@end verbatim
+@noindent
+La marcatura temporale aggiunta al nome nei file di backup rende
+facile trovare la copia più recente se il file sparso è danneggiato,
+anche se l'informazione sull'ultima data di modifica sia stata
+inavvertitamente modificata.
+
+@c TODO:  sync individual files above instead of globally (?)
+@c        First carefully check what sync does in both cases
+@c        using strace, verify that "sync [file]" is correct.
+@c        Also check whether non-GNU/Linux offers fine-grained
+@c        sync command.  Cygwin?  Solaris?
+
+L'opzione @command{--reflink} del comando @command{cp} riduce sia
+l'utilizzo di memoria su disco che il tempo richiesto per effettuare
+la copia.  Allo stesso modo un cui i file sparsi offrono della
+memoria su disco del tipo  ``paga solo per ciò che utilizzi'',
+la copia di tipo reflink offre della memoria del tipo
+``paga solo per ciò che @emph{modifichi}''.@footnote{La chiamata-a-sistema
+che implementa la copiatura di tipo reflink è descritta nella
+pagina di manuale del comando @command{ioctl_ficlone}.}
+Una copia reflink condivide memoria col file originale.
+Il filesystem garantisce che ulteriori modifiche a uno dei
+due file non riguarderà l'altro.  La copia con reflink non
+è disponibile per tutti i filesystem; al momento è supportata
+dai filesystem di tipo XFS, BtrFS, e OCFS2.@footnote{L'opzion
+@command{--reflink} crea copie di un file sparso mantenendolo
+tale.  Se la copiatura con reflink non è disponibile, si dovrebbe
+usare invece l'opzione @command{--sparse=always}.}
+Fortunatamente è possibile installare, per esempio, un filesystem
+XFS @emph{all'interno di un file ordinario} in qualche altro
+filesystem, come @code{ext4}.@footnote{Vedere
+@url{https://www.usenix.org/system/files/login/articles/login_winter19_08_kelly.pdf}.}
+
+@c The @command{filefrag} utility reveals how the storage allocated to
+@c the two files changes if they diverge.
+
+Dopo aver creato una copia di backup del file sparso, usiamo il
+comando @command{sync} per forzare la scrittura dalla memoria a
+un disco.  In caso contrario la copia potrebbe risiedere sono nella
+memoria volatile DRAM---nella cache del filesystem---dove una
+caduta del sistema o una mancanza di corrente potrebbero
+corromperla.@footnote{In alcuni Sistemi Operativi il comando
+@command{sync} non garantisce molto, ma in ambiente Linux
+@command{sync} termina sono quando tutti i dati di filesystem
+sono stati scritti su una memoria durevole.
+Se nel vosgtro sistema @command{sync} è inaffidabile, si può
+scrivere un piccolo programma in C che invochi la chiamata-a-sistema
+@code{fsync()} per forzare la scrittura di un file.  Per maggiore
+sicurezza, è meglio chiamare @code{fsync()} per ogni directory
+a livello superiore nel percorso del file (@code{realpath()})
+fino a giungere alla @dfn{root}.}  Dopo aver usato @command{sync}
+sul backup, creiamo e forziamo la scrittura con @command{sync} di
+un file ``indicatore di successo'' con una estensione @file{.fatto}
+per prevenire un pericoloso evento, che potrebbe succedere:
+ci può essere una mancanza di corrente @emph{mentre} un file
+di backup è copiato dal file sparso originale, lasciando uno dei
+file (o entrambi) corrotti in memoria---una possibilità
+particolarmente preoccupante, per lavori che vengono eseguiti
+senza un operatore presente.  Dopo una ripartenza, ogni file
+@file{.fatto} attesta che il corrispondente backup è andato a
+buon fine, facilitando il riconoscimento del backup riuscito
+più recente.
+
+@c TODO:  ".done" -> ".ready" so ls alphabetizes nicely (?)
+
+Per finire, se si è seriamente intenzionati a ovviare a
+eventuali problemi hardware/software si deve essere
+``addestrati come per combattere'' testando il vostro
+hardware/software contro dei problemi che realisticamente possono
+presentarsi.  Per un realistico test dei problemi correlati
+alle mancanze di corrente, vedere [in inglese]
+@c 
@url{https://cacm.acm.org/magazines/2020/9/246938-is-persistent-memory-persistent/fulltext}
+@c
+@c and
+@url{https://queue.acm.org/detail.cfm?id=3400902}.
+
+@c @page
+@sp 3
+@c ==================================================================
+@node    Ringraziamenti
+@chapter Ringraziamenti
+
+@c UPDATE:  make sure nobody is overlooked
+
+Haris Volos, Zi Fan Tan e Jianan Li hanno sviluppato una versione
+prototipo persistente di @gwk{}, a partire da una diramazione
+del codice sorgente di @gwk{}.
+I consigli che ho ricevuto dal manutentore di @gwk{},
+Arnold Robbins, e che ho inoltrato a loro, sono risultati essere
+molto utili.  Robbins, inoltre, ha implementato, documentato e
+testato @pmg{} per la versione ufficiale di @gwk{}; strada facendo,
+egli ha suggerito numerosi miglioramenti per l'allocatore di
+memoria @code{pma} che sta dietro a @pmg{}.  Corinna Vinschen
+ha suggerito altri miglioramenti a @code{pma} e testato @pmg{}
+in ambiente Cygwin.  Nelson H.@: F.@: Beebe ha fornito accesso
+a macchine Solaris durante la fase di test.  Robbins, Volos, Li,
+Tan, Jon Bentley e Hans Boehm hanno rivisto le bozze di questo
+manuale utente, e le loro osservazioni sono state utili.
+Bentley ha suggerito l'esempio minimo/massimo/media
+nel @ref{Esempi}, e anche l'esercizio di rendere persistente
+lo script ``Markov'', tratto dal testo di Kernighan e Pike.
+Volos ha fornito e testato i suggerimenti sulla regolazione dei
+parametri del Sistema Operativo nella @ref{Memoria virtuale e file enormi}.
+Stan Park ha fornito degli approfondimenti riguardo a
+memoria virtuale, filesystem  e programmi di utilità.
+
+@c ==================================================================
+@c ==================================================================
+@c ==================================================================
+
+@node    Installazione
+@appendix Installazione
+
+@c UPDATE below or remove this section if it's obsolete
+
+@gwk{} 5.2 con la Memoria Persistente dovrebbe essere disponibile a
+settembre 2022; lo si troverà in @url{http://ftp.gnu.org/gnu/gawk/}.
+Se la versione 5.2 non è ancora rilasciata, la diramazione sorgente
+@dfn{master} sotto git è disponibile in
+@c
+@url{http://git.savannah.gnu.org/cgit/gawk.git/snapshot/gawk-master.tar.gz}.
+@c
+Scompattate il file di distribuzione, eseguite i comandi
+@command{./bootstrap.sh}, @command{./configure}, @command{make}, e
+@command{make check}, e poi sarete in grado di testare qualcuno degli
+esempi presentati sopra.  Col passare del tempo le versioni
+5.2 e successive di @gwk{}, che includono @pmg{} saranno incluse
+nei pacchetti di gestione del software delle maggiori distribuzioni
+GNU/Linux.  Quindi, in futuro, @pmg{} sarà disponibile
+nel comando @gwk{} di default per tali sistemi.
+
+@c ADR comments on above, "run ./bootstrap.sh, ./configure ..."
+@c TK replies: I haven't been doing this.  Neither the README nor the
+@c    INSTALL in the gawk tarball mention bootstrap.sh.  If it's
+@c    important, shouldn't they?  The top of bootstrap.sh says its
+@c    purpose is "to avoid out-of-date issues in Git sandboxes."
+@c    When a neurodivergent source code control system requires us to
+@c    write shell scripts to work around the problems that it creates
+@c    gratuitously, the universe is trying to tell us something about
+@c    it.
+
+@c official gawk:
+@c http://ftp.gnu.org/gnu/gawk/                                               
[where to look for 5.2 after release]
+@c https://www.skeeve.com/gawk/gawk-5.1.62.tar.gz                             
[doesn't support persistent functions]
+@c http://git.savannah.gnu.org/cgit/gawk.git/snapshot/gawk-master.tar.gz      
[if 5.2 isn't released yet]
+@c http://git.savannah.gnu.org/cgit/gawk.git                                  
[ongoing development]
+
+@c ==================================================================
+@node    Debugging
+@appendix Debugging
+
+@c TODO:  ADR:  @cite -> @ref to info file below
+
+Per bug non correlati alla persistenza, vedere la documentazione
+@gwk{}, e.g., @cite{GAWK: Effective AWK Programming},
+disponibile in @url{https://www.gnu.org/software/gawk/manual/}.
+[La versione italiana dello stesso libro è disponibile in
+@url{https://sites.google.com/view/gawkdoc-it/home-page}.]
+
+Se @pmg{} non si comporta secondo le attese, dovreste per prima
+cosa domandarvi se state usando il file sparso che intendevate
+usare; usare il file sbagliato è un errore comune.
+Altre feconde sorgenti di bug per principianti sono il fatto che
+una regola @code{BEGIN} è eseguita ogni volta che si invoca
+@pmg{}, il che non è sempre ciò che veramente si vuole, nonché
+il fatto che le variabili predefinite di AWK, come per esempio
+@code{NR} sono sempre inizializzate a zero ogni volta che si
+invoca il programma.  Vedere la trattazione dell'inizializzazione
+per lo script minimo/massimo/media nel @ref{Esempi}.
+
+Se si sospetta che un bug sia connesso con la persistenza in @pmg{},
+si può impostare una variabile d'ambiente che farà sì che il codice
+@code{pma}, che si occupa della persistenza, invii dei messagi
+diagnostici più numerosi; per i dettagli, si veda la documentazione
+principale di @gwk{}.
+@c or the @code{pma} documentation at
+@c @url{http://web.eecs.umich.edu/~tpkelly/pma/}.
+
+Programmatori: Si può ricompilare @gwk{} abilitando delle asserzioni,
+il che causerà degli estesi controlli di integrità all'interno
+del codice @code{pma}.  Assicuratevi che il sorgente @file{pma.c}
+sia compilato @emph{senza} il flag @code{-DNDEBUG}, quando si
+compila @gwk{} usando il comando @command{make}.
+Il programma eseguibile che ne risulta dovrebbe essere testato
+con input piccoli, perché i controlli di integrità possono
+rallentare di molto l'esecuzione.
+Se qualche asserzione fallisce, significa che c'è un bug
+da qualche parte in @pmg{}.  Tali bug vanno segnalati a me
+(Terence Kelly) come pure seguendo le procedure indicate
+nella documentazione principale di @gwk{}.  Specificate quale
+versione di @gwk{} si sta usando, e cercate di fornire uno
+script piccolo e semplice che permetta di riprodurre
+il bug in maniera affidabile.
+
+@c @page
+@sp 3
+@c ==================================================================
+@node     Storia
+@appendix Storia
+
+La funzionalità di Memoria Persistente in @pmg{} si basa su un nuovo
+Allocatore di Memoria Persistente, @code{pma}, le cui specifiche
+di progettazione [in inglese] sono descritte in
+@url{https://queue.acm.org/detail.cfm?id=3534855}.  È istruttivo
+ripercorrete le fasi dell'evoluzione che ha condotto a
+@code{pma} e @pmg{}.
+
+Ho preparato parecchi script AWK durante le ricerche per la mia
+tesi di laurea sul Web caching, la maggior parte dei quali analizzava
+file di log provenienti da server Web e da cache Web.  Avere a
+disposizione @gwk{} con la Memoria Persistente avrebbe reso questi
+script più piccoli, più veloci, e più facili da scrivere, ma allora
+non ero neppure in grado di immaginare che @pmg{} sarebbe stato possibile.
+Quindi ho scritto un mucchio di codice inefficiente e tedioso che
+manualmente creava e ricaricava variabili AWK utilizzando file di
+testo.  Un decennio doveva passare prima che i miei colleghi e io
+iniziassimo a mettere insieme i pezzi che hanno reso possibile
+script che usano la Memoria Persistente, e un altro decennio sarebbe
+passato prima che @pmg{} fosse reso in grado di operare.
+
+All'incirca nel 2011, mentre lavoravo agli HP Labs, ho sviluppato
+una piattaforma di calcolo distribuito tollerante agli errori,
+chiamata ``Ken'', che conteneva un allocatore di Memoria Persistente
+che assomigliava a una versione semplificata di @code{pma}: rendeva
+disponibile una interfaccia in linguaggio C simile a @code{malloc()}
+e allocava memoria tramite una mappatura della memoria, che era
+mantenuta anche su un file.  L'esperienza fatta con Ken mi convinse
+che l'astrazione software della Memoria Persistente è molto
+attraente, rispetto alle alternative, per gestire dati persistenti
+(p.es., database relazionali e depositi chiave-valore).
+Sfortunatamente, l'allocatore di memoria di Ken è così profondamente
+interconnesso col resto di Ken da risultare praticamente
+inseparabile; per poter fruire dei benefici della Memoria
+Persistente di Ken occorreva ``comprare'' anche una vasta serie di
+altro complicato software.  Quali che fossero i suoi altri pregi,
+Ken non è l'ideale per servire da esempio riguardo ai benefici
+della Memoria Persistente in se stessa.
+
+Un altro aspetto convoluto di Ken era un meccanismo per resistere
+ai crash del computer che, in retrospettiva, può essere visto come
+un'implementazione a livello di utente di quello che fa la chiamata
+a sistema @code{msync()} resistente a un crash.
+Il primo sforzo di estrazione del dopo-Ken ha estratto il meccanismo
+di resistenza ai crash, e l'ha implementato nel kernel Linux, e il
+risultato è stato definito ``failure-atomic @code{msync()}''
+(FAMS -- @code{msync()} resistente a un crash).  FAMS rafforza il
+significato del normale comando @code{msync()} garantendo che lo stato
+permanente di un file mappato in memoria rifletta sempre la più
+recente chiamata a @code{msync()}, perfino in presenza di eventi
+come una mancanza di corrente e di crash sia a livello di programma
+che di Sistema Operativo.  Il prototipo originale del FAMS nel
+kernel Linux è descritto in un saggio di Park @dfn{et al.} negli
+atti del convegno EuroSys 2013.  I miei colleghi e io abbiamo in
+seguito implementato FAMS in parecchie maniere differenti,
+fra cui i filesystem (FAST 2015) e le librerie a livello
+di utente.
+La mia implementazione più recente di FAMS, che utilizza la
+funzionalità di copiatura reflink, descritta in altra parte di
+questo manuale, è ora alla base di una nuova funzionalità di
+resistenza ai crash nel venerabile e onnipresente comando GNU
+@command{dbm} (@command{gdbm}) per gestire dei database
+(@url{https://queue.acm.org/detail.cfm?id=3487353}).
+
+Negli ultimi anni la mia attenzione è tornata sui vantaggi
+della Memoria Persistente nella programmazione, che è
+diventata un argomento ``caldo'' grazie alla disponibilità
+commerciale di memoria non-volatile indirizzabile a byte
+(che, per confondere le idee, è oggi etichettata come
+``Memoria Persistente'').  L'astrazione software della
+Memoria Persistente e il corrispondente stile di programmazione
+sono perfettamente compatibili con dei computer
+@emph{convenzionali}---macchine non dotate di memoria non-volatile
+e neppure di altro software e hardware particolari.
+Ho scritto alcuni saggi per spiegare questo punto, per esempio
+[in inglese]
+@url{https://queue.acm.org/detail.cfm?id=3358957}.
+
+A inizio 2022 ho scritto un nuovo allocatore di memoria persistente,
+a sé stante, @code{pma}, per facilitare l'uso della Memoria Persistente
+su hardware convenzionale.  L'interfaccia @code{pma} è compatibile
+con la chiamata a sistema @code{malloc()} e, a differenza
+dell'allocatore presente in Ken, @code{pma} non è collegato a un
+particolare meccanismo di resistenza ai crash.  Usare @code{pma}
+è facile e, almeno per alcuni, piacevole.
+
+Ken è stato integrato in prototipi derivanti sia dall'interprete
+di Javascript V8 che da un interprete Scheme, e quindi è parso
+naturale domandarsi se @code{pma} avrebbe analogamente potuto
+potenziare un linguaggio interpretato di script.
+GNU AWK è stata una scelta naturale perché il codice sorgente
+è ordinato, e perché @gwk{} ha un solo manutentore principale,
+con una mente aperta riguardo all'aggiunta di nuove funzionalità.
+
+Jianan Li, Zi Fan Tan, Haris Volos, e io abbiamo iniziato a prendere
+in esame la persistenza per @gwk{} alla fine del 2021.  Mentre io
+stavo scrivendo @code{pma}, essi hanno preparato un prototipo di
+@pmg{} a partire da una diramazione della distribuzione
+sorgente ufficiale di @gwk{}.
+L'esperienza con il prototipo ha confermato la convenienza e i
+benefici per le prestazioni di @pmg{}, e a partire dalla primavera
+del 2022 Arnold Robbins ha iniziato a implementare la persistenza
+nella versione ufficiale di @gwk{}.  La funzionalità di Memoria
+Persistente nel comando @gwk{} ufficiale è lievemente differente da
+quella del prototipo: la prima usa una variabile d'ambiente per
+comunicare all'interprete il nome del file sparso, mentre l'altra
+usava un'opzione obbligatoria da inserire nella riga-di-comando.
+Per molti aspetti, comunque, le due implementazioni sono simili.
+Una descrizione del prototipo, con anche delle misurazioni di
+prestazioni è disponibile in
+@url{http://nvmw.ucsd.edu/nvmw2022-program/nvmw2022-data/nvmw2022-paper35-final_version_your_extended_abstract.pdf}.
+
+@c lessons learned  [these are smallish ideas]
+@c    compatibility with malloc
+@c    make programmer do *nothing*
+@c    components (pma) are easier to sell than monoliths (Ken)
+@c    open source offers more impact than research
+@c    work with colleagues who Think Different from one another
+
+@sp 2
+
+Mi piacciono parecchie cose di @pmg{}.  Non è invadente; man mano
+che acquisite familiarità ed esperienza, scivola sullo sfondo
+della vostra programmazione.  È semplice sia come concetto che come
+implementazione e, cosa ancora più importante, semplifica i vostri
+script; molto del suo valore si apprezza non tanto nel codice che
+mette in grado di scrivere, quanto nel codice che consente di
+eliminare. È tutto ciò (e anche più) di cui avevo bisogno nella mia
+tesi di laurea vent'anni fa.  Guardando ai fatti, sembra ispirare
+la creatività di coloro che l'hanno adottato per primi.  Sono curioso
+di vedere quali nuove finalità di utilizzo si possono trovare
+per esso.
+
+@c ==================================================================
+@c ==================================================================
+@c ==================================================================
+
+@bye
+
+@c ==================================================================
+@c ==================================================================
+@c ==================================================================
+

-----------------------------------------------------------------------

Summary of changes:
 doc/it/ChangeLog      |    6 +
 doc/it/README.txt     |   23 +-
 doc/it/compila_pma.sh |   11 +
 doc/it/pm-gawk.texi   | 1610 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1643 insertions(+), 7 deletions(-)
 create mode 100755 doc/it/compila_pma.sh
 create mode 100644 doc/it/pm-gawk.texi


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]