¿Dónde está mi memoria?–Lock Pages in Memory (x64)

Acabamos de comprar un flamante nuevo servidor, 24 cores, 128GB de RAM, discos SSD en RAID 0… Instalamos SQL Server, 64 bits por supuesto, activamos Lock Pages in Memory (https://msdn.microsoft.com/en-us/library/ms190730.aspx) para que SQL no sea paginado fuera de RAM. Y para deleitarnos con nuestra obra cogemos contadores de carga de CPU, bloqueos, memoria…. Y ahí empieza el problema, ¡dónde está mi memoria!

La memoria puede estar “perdida”, entre comillas ya que la memoria está siendo realmente usada, por diversos motivos, para los ejemplos usaré mi modesto Xeon de 4 cores y 12GB de RAM. Para capturar el uso de RAM física se usara la herramienta RAMMap de Mark Russinovich y Bryce Cogswell que podemos bajar de sysinternals: https://technet.microsoft.com/en-us/sysinternals/ff700229

1 – Task Manager y lock pages in memory.

Para realizar las pruebas se hace una SELECT de 10.000.000 de registros.

Si usamos task manager para comprobar el uso de RAM de SQL podemos llevarnos una sorpresa.

image

Esta memoria es el Working Set (la memoria física usada actualmente por SQL Server). Apenas 116MB de uso, esto no cuadra con una base de datos que mueve cientos, miles o millones de datos por segundo por tanto algo debe estar mal.

Si vamos a Management Studio y ejecutamos

DBCC MEMORYSTATUS

SQL nos proporcionará un resumen del uso de RAM que para nada coincidirá con lo que nos indica el task manager.

Memory Manager KB
---------------------------------------- -----------
VM Reserved 19015912
VM Committed 119148
Locked Pages Allocated 747776
Reserved Memory 1024
Reserved Memory In Use 0

Vamos a fijarnos únicamente en los valores VM Committed y Locked Pages Allocated (AWE Allocated en SQL Server 2005).

VM Commited: Éste valor es el tamaño de memoria virtual (del proceso) que actualmente está siendo manejado por SQL Server, esta memoria puede ser paginada, el working set es un sub conjunto de esta memoria, por tanto los valores obtenidos tienen lógica.

Locked Pages Allocated (AWE allocated en SQL Server 2005): Este valor indica la cantidad de RAM física bloqueada en memoria por SQL Server y que no se puede ser paginada. Por tanto esta valor más el working set nos darán una idea aproximada del tamaño de la RAM física consumida por SQL Server (En este caso 118972KB + 747776KB, unos 846MB)

La explicación de este comportamiento es que al activar  Lock Pages in Memory en x64 se está haciendo uso de algo muy conocido por la gente que ya ha trabajado con SQL en x86, me refiero a: Address Windowing Extensions (AWE) https://msdn.microsoft.com/en-us/library/aa366527(v=vs.85).aspx. Esta API sigue estando presente en las ediciones de 64 bits de Windows debido a su utilidad ya que es la única forma que tiene un programa de usuario de bloquear RAM física para su uso. Para los programadores que tenga curiosidad les recomiendo que vean la entrada de msdn VirtualAlloc(https://msdn.microsoft.com/en-us/library/aa366887(v=vs.85).aspx) con el flag MEM_PHYSICAL. Esta memoria está fuera de la memoria virtual del proceso y por tanto no aparece en el Working Set del Task Manager.

A continuación lanzamos RAMMap para ver en que se está usando la RAM física.

image

Como podemos ver el valor consumido por AWE coincide exactamente con el de Lock Pages Allocated, 744776KB.

Hemos encontrado nuestra memoria.

2 – Lock Pages Allocated no coincide con el valor de AWE. Presentamos “Large Page Extensions”

Ahora realizamos la misma prueba con una máquina i7 de 4 cores y 16GB de RAM. Arrancamos SQL Server, lanzamos Management Studio, hacemos una SELECT de 10.000.000 de registros y…

image

Un working set de 131468KB. Mas o menos como antes. Ahora veamos la salida de DBCC MEMORYSTATUS

Memory Manager KB
---------------------------------------- -----------
VM Reserved 23200928
VM Committed 174292
Locked Pages Allocated 682048
Reserved Memory 1024
Reserved Memory In Use 0

Parece que todo está mas o menos como en el ejemplo anterior, 174292KB para VM Commited y 682048KB para Lock Pages Allocated. Pero cuando vamos a RAMmap vemos esto:

image

Y… oops. AWE está consumiendo 731200de RAM, lo que nos deja con la siguiente pregunta ¿Donde están mis 48MB?

La respuesta está en “Large Page Extension” (https://msdn.microsoft.com/en-us/library/aa366720.aspx). Basicamente SQL Server 64bits si se encuentra más de 8GB libres al arrancar usará parte de la memoria para "Large Pages” este tipo de páginas de memoria proporcionan un aumento de rendimiento para grandes cargas de datos y se reserva usando el API de AWE, por tanto RAMMap la muestra como memoria AWE, mas información (https://blogs.msdn.com/b/psssql/archive/2009/06/05/sql-server-and-large-pages-explained.aspx). Si en vez de utilizar DBCC MEMORYSTATUS usamos DMV’s podremos ver este tipo de reservas de memoria. Usaremos la siguinte query (Esta query solo funciona en SQL Server 2008 y superiores):

SELECT large_page_allocations_kb, locked_page_allocations_kb FROM sys.dm_os_process_memory

En mi caso el resultado es el siguiente:

image

Lo que nos dice que 682048KB están en Locked Pages y 49152KB están en Large Pages, lo que nos suma los 731200KB. En caso de SQL Server 2005 no hay ninguna query con la que podamos consultar este tipo de memoria, con lo que tendremos que hacer un acto de fe.

Notas sobre Large Pages:

- Solo está disponible en Developer y Enterprise

- Cuanto más RAM tenga el sistema más RAM se reserva para Large Pages.

- Las Large Pages solo se activan si tenemos más de 8GB libres cuando arranca SQL Server.

- Large Pages no está limitado por Max Server Memory.

- Con mirar nuestro ERROLOG sabremos si están activas las Large Pages, se registrara lo siguiente:

2011-09-02 13:13:47.41 Server Large Page Extensions enabled.
2011-09-02 13:13:47.41 Server Large Page Granularity: 2097152
2011-09-02 13:13:47.41 Server Large Page Allocated: 32MB
2011-09-02 13:13:47.43 Server Using locked pages for buffer pool.

Pablo Gavela López – Microsoft Customer Support Services