Introduzione

Nell'ambito del Memory Manager di Windows un concetto interessante, e talvolta poco approfondito, è quello delle "System PTE". L'obiettivo di questo post è di definire queste entità, chiarirne il loro ruolo e distinguerle dalle comuni PTE. Infine le risorse associate alle System PTE necessitano talvolta di monitoring e tuning, per questa parte si farà riferimento ad un prossimo post più specifico su questa parte.

PTE

Una PTE (Page Table Entry) è l' elemento di base per il mapping tra la memoria virtuale (o logica) e quella fisica. La memoria virtuale viene divisa in pagine, la dimensione di una pagina può variare a seconda dell'architettura del processore, per esempio x86 e x64 definiscono entrambi pagine di 4KB (4096 byte) mentre Itanium ha una pagina di 8KB. Ogni pagina virtuale può avere una PTE associata che descrive se essa è valida (ovvero disponibile al processore) ed in caso affermativo quale pagina di memoria fisica corrisponde alla pagina virtuale di interesse. In termini pratici, prendendo come esempio l'architettura x86, più semplice, lo spazio di indirizzi virtuale è di 4GB, con pagine di 4KB avremo circa un milione di pagine (precisamente 1024*1024=1.048.576), potenzialmente per ciascuna di esse potremmo avere una PTE nella quale ci saranno le informazioni appena citate.

Con questo meccanismo il processore sarà in grado di leggere o scrivere una pagina di memoria virtuale valida andando ad accedere la corrispondente pagina fisica, l'informazione per il passaggio da virtuale a fisica avviene tramite le informazioni nella PTE.

La dimensione di una PTE dipende dall'architettura per x86 e x64 le PTE assumono le seguenti grandezze:

Architettura

Dimensione della PTE

x86 non PAE(*)

4 byte

x86 PAE(*)

8 byte

X64

8 byte

(*) PAE = Page Addressing Extension - Meccanismo che permette di installare 64GB o 128GB di memoria anziché i 4GB originalmente consentiti nell'architettura x86.

Oltre all'informazione sulla validità della pagina virtuale e l'eventuale riferimento alla pagina fisica la PTE contiene informazioni di accesso, ad esempio se è una pagina read/write, read only o execute (codice eseguibile), se è stata acceduta dal momento in cui era stata resa valida e se è stata modificata.

Quando la PTE indica che la pagina non è valida le informazioni appena citate diventano irrilevanti. Allora la PTE può essere usata dal sistema operativo per tenere traccia di come reperire la pagina "swapped out", ovvero dove trovarla dal paging file.

Per completezza è necessario chiarire che un gran numero di pagine virtuali possono non avere alcuna PTE associata. In tal caso un tentativo di accesso viene intercettato in una struttura che gerarchicamente viene prima della PTE (p.es. PDE, Page Directory Entry). A seconda del particolare range di indirizzi acceduto il sistema operativo potrà poi decidere se creare la PTE, rendere valida la pagina o sollevare un'eccezione di "access violation", indicativa di un tentativo di accesso ad una pagina di memoria non valida (e che non avrebbe potuto essere resa valida recuperando la pagina da disco).

Come si può intuire dagli espliciti riferimenti alle architetture qui sopra la PTE è definita dal processore ed i sistemi operativi ne gestiscono i contenuti con i formati definiti dall'hardware.

System PTE

Le System PTE sono un particolare sottoinsieme di tutte le PTE e servono al sistema per il mapping di un'area di memoria particolare, assegnata al kernel. Il kernel di Windows, tanto il sistema stesso che moduli e device driver, allocano memoria per i loro usi primariamente dalle pool: paged e non-paged pool. In alcuni casi le caratteristiche di queste ultime due risorse non le rendono adatte a certi scopi e pertanto il sistema necessita di una terza risorsa che è appunto l'area di memoria mappata dalle System PTE.

Relativamente alla terminologia è da osservare che, in alcuni contesti, il termine System PTE può far riferimento al particolare tipo di PTE appena descritte o intercambiabilmente all'area di memoria che esse vanno a mappare. In un post precedente Kernel Memory Overview è riportato un cenno alle due pool e le system PTE, con particolare riferimento ai loro usi tipici. La seguente tabella aggiunge un confronto tra le loro caratteristiche salienti:

Tipo di risorsa

System PTE

Paged pool

Non-paged pool

Granularità di allocazione

Pagina (4 KByte per x86 e x64)

1 byte (arrotondato ad 8 byte internamente)

1 byte (arrotondato ad 8 byte internamente)

Uso

  • stack kernel
  • memory mapped device
  • alcuni tipi di video buffer
  • buffer di memoria per trasferimenti di tipo DMA (Direct Memory Access)
  • Allocazioni kernel del sistema operativo per usi generici
  • Allocazioni nei driver per usi generici
  • Allocazioni kernel del sistema operativo che necessitano di essere acceduti ad IRQL(**) elevato
  • Allocazioni nei driver che necessitano di essere acceduti ad IRQL(**) elevato

Paginabilità

Controllata direttamente dal sistema per singola allocazione

Può essere "swapped out" quando necessario

Sempre residente (mappata) su memoria fisica

(**) IRQL = Interrupt Request Level - Meccanismo di mascheramento degli interrupt in base ad un livello di priorità.

Da un punto di vista pratico le System PTE sono importanti perché quando scarseggiano il sistema potrebbe diventare instabile. In particolare, facendo riferimento alla tabella qui sopra, vediamo che i trasferimenti DMA (Direct Memory Access) possono appoggiarsi su questo tipo di memoria. Dischi e network drivers sono tipici utilizzatori di trasferimenti DMA, come anche altri dispositivi, ci sono inoltre altre funzioni importanti associate alle System PTE. In termini pratici si considera come linea guida di non scendere mai sotto le 15.000 System PTE quando il server è sotto il massimo carico. E' da osservare che l'area di memoria in questione, come molte risorse dinamicamente allocabili, può essere soggetta a frammentazione, quindi anche quando la richiesta di un determinato blocco fosse inferiore alla disponibilità totale, essa poterebbe fallire per l'impossibilità di trovare un blocco contiguo che la soddisfi.

Il valore delle System PTE può essere monitorato con il performance monitor osservando l'oggetto "Memory" counter "Free System Page Table Entries". L'indicazione del totale disponibile è invece osservabile tramite una sessione di kernel debugging (eventualmente local kernel debugging) o un dump della macchina.

Il valore sopra riportato di 15.000 System PTE corrisponde ad un'area di memoria di poco meno di 60MB. In generale per convertire il numero di PTE nel corrispondente spazio che descrivono bisogna moltiplicare per 4096 (4Kbyte), ovvero la dimensione di una pagina, visto che, in accordo a quanto citato, ogni PTE descrive una pagina di memoria.

In configurazioni con spazi di indirizzi limitati per il kernel, come ad esempio x86 o ancor di più x86 con lo switch /3GB nel boot.ini, il sistema operativo deve suddividere al meglio questo spazio tra le pool, le System PTE ma anche altro, come il codice eseguibile del kernel stesso, dell'hal, dei device driver, e ancora i memory mapped file e la cache di sistema. Evidentemente esiste una contesa tra queste risorse in modo particolare tra le due pool e le System PTE (in realtà la memoria mappata tramite le system PTE), questa contesa è resa ancora più evidente nei sistemi pre-Vista dove il memory manager le configura staticamente al boot.

Talvolta viene ipotizzato che passando da una configurazione senza PAE, in cui ogni PTE è di 4 byte, ad una con il PAE abilitato, che raddoppia la dimensione delle PTE, il numero di System PTE si dimezzi. Questo non avviene perché, in base a quanto visto sopra, la risorsa preziosa non sono le System PTE stesse bensì l'area di memoria che descrivono, ovvero il range di indirizzi virtuali che viene assegnato a quest'area.

Una configurazione con lo switch /3GB (solo x86) invece penalizza seriamente lo spazio di indirizzi del kernel e quindi le System PTE si riducono sensibilmente, come accade anche alle due pool.

Conclusioni

L'obiettivo primario di questo post era di fornire le basi teoriche sulle System PTE.

Inoltre, per i motivi che sono stati illustrati, è molto importante garantire una adeguata disponibilità di System PTE, e conseguentemente della memoria ad esse associata.

Nelle configurazioni x86, in particolare su Windows Server 2003 con /3GB, è spesso necessario monitorare ed eventualmente fare un tuning di queste risorse. Prima di procedere in questo senso è necessario considerare l'alternativa di un sistema a 64 bit che non è soggetto a queste restrizioni con uno spazio di indirizzi enormemente più ampio. Ad esempio aree di memoria, come le pool o le System PTE, passano dall'ordine di grandezza delle centinaia di MB a centinaia di GB in x64.

Come soluzione secondaria o per ottimizzare un sistema in attesa di un upgrade a 64 bit può ugualmente rendersi necessario un tuning. In un prossimo post verranno descritte queste operazioni in dettaglio e con riferimento agli strumenti pratici per svolgerle.

Nei sistemi a 64 bit la maggiore disponibilità elimina in modo sostanziale i problemi di tuning, similmente anche i sistemi a 32 bit Vista o seguenti gestiscono un ridimensionamento dinamico di queste aree quindi diminuendo anche in questo caso la necessità del tuning delle loro dimensioni iniziali. Le System PTE rimangono comunque di primaria importanza ed il sistema non deve essere soggetto a leak di questa risorsa. In presenza di problemi di questo tipo il loro spreco sarebbe destinato a portare il sistema all'esaurimento e, se non interviene prima un reboot, all'instabilità.

E' quindi importante assicurarsi che non vi siano leak di questo genere, il primo passo per fare questa verifica è il monitoring tramite performance monitor del counter citato nel post (Memory/Free System Page Table Entries).

 

Fabio Lavatelli
Escalation Engineer
Microsoft Enterprise Platform Support