pro original gratis español descargar como actualizacion windows delphi winapi virtual-memory delphi-5

original - windows 10 pro



¿Qué puede hacer mi aplicación de 32 bits que consume gigabytes de RAM física? (1)

Lo más probable es que en algún lugar de su aplicación esté asignando recursos del sistema y no los esté liberando. Cualquier llamada de WinApi que cree un objeto y devuelva un identificador podría ser sospechosa. Por ejemplo (tenga cuidado al ejecutar esto en un sistema con memoria limitada; si no tiene 6GB gratis, la página se cargará mal):

Program Project1; {$APPTYPE CONSOLE} uses Windows; var b : Array[0..3000000] of byte; i : integer; begin for i := 1 to 2000 do CreateBitmap(1000, 1000, 3, 8, @b); ReadLn; end.

Esto consume 6 GB de memoria de sesión debido a la asignación de objetos de mapa de bits que no se liberan posteriormente. El consumo de memoria de la aplicación sigue siendo bajo porque los objetos no se crean en el montón de la aplicación.

Sin embargo, sin saber más sobre su aplicación, es muy difícil ser más específico. Lo anterior es una forma de demostrar el comportamiento que está observando. Más allá de eso, creo que necesitas depurar.

En este caso, hay una gran cantidad de objetos GDI asignados; sin embargo, esto no es necesariamente indicativo, ya que a menudo hay una gran cantidad de objetos GDI pequeños asignados en una aplicación en lugar de una gran cantidad de objetos grandes (el IDE de Delphi). , por ejemplo, creará rutinariamente> 3000 objetos GDI y esto no es necesariamente un problema).

En el ejemplo de @ Abelisto (en comentarios), por el contrario:

Program Project1; {$APPTYPE CONSOLE} uses SysUtils; var i : integer; sr : TSearchRec; begin for i := 1 to 1000000 do FindFirst(''c:/*'', faAnyFile, sr); ReadLn; end.

Aquí, los controladores devueltos no corresponden a objetos GDI, sino que son controladores de búsqueda (que se encuentran en la categoría general de Objetos de Kernel). Aquí podemos ver que hay un gran número de manejadores utilizados por el proceso. Nuevamente, el consumo de memoria de proceso es bajo, pero hay un gran aumento en la memoria de sesión utilizada.

De manera similar, los objetos pueden ser Objetos de usuario: estos se crean mediante llamadas a elementos como CreateWindow , CreateCursor o mediante la configuración de CreateCursor con SetWindowsHookEx . Para obtener una lista de las llamadas de WinAPI que crean objetos y devuelven controladores de cada tipo, consulte:

Manijas y objetos: Categorías de objetos - MSDN

Esto puede ayudarlo a comenzar a rastrear el problema al reducirlo al tipo de llamada que podría estar causando el problema. También puede estar en un componente de terceros con errores, si está utilizando alguno.

Una herramienta como AQTime puede perfilar las asignaciones de Windows, pero no estoy seguro de si hay una versión que admita Delphi5. Puede haber otros perfiladores de asignación que pueden ayudar a rastrear esto.

Un compañero de trabajo me mencionó hace unos meses que una de nuestras aplicaciones internas de Delphi parece estar ocupando 8 GB de RAM. Le dije:

Eso no es posible

Una aplicación de 32 bits solo tiene un espacio de direcciones virtuales de 32 bits. Incluso si hubiera una pérdida de memoria, la mayor cantidad de memoria que podría consumir es de 2 GB. Después de eso, las asignaciones fallarían (ya que no habría espacio vacío en el espacio de direcciones virtuales). Y en el caso de una pérdida de memoria, las páginas virtuales se cambiarán al archivo de paginación, liberando RAM física.

Pero señaló que el Monitor de recursos de Windows indicó que había menos de 1 GB de RAM disponible en el sistema. Y mientras nuestra aplicación solo usaba 220 MB de memoria virtual: al cerrarla liberé 8 GB de RAM física.

Así que lo probé

Dejé que la aplicación se ejecutara durante unas semanas, y hoy finalmente decidí probarlo.

Primero miro el uso de la memoria antes de cerrar la aplicación:

  • El conjunto de trabajo (RAM) es de 241 MB.
  • memoria virtual total utilizada: 409 MB

Y utilicé el Monitor de recursos para verificar la memoria utilizada por la aplicación y la RAM total en uso:

  • Memoria virtual asignada por aplicación: 252 MB
  • Memoria física en uso: 14 GB.

Y luego el uso de la memoria después de cerrar la aplicación:

  • Memoria física en uso: 6.6 GB (7.4 GB más bajo)

También utilicé Process Explorer para ver un desglose del uso físico de RAM antes y después. La única diferencia es que 8 GB de RAM realmente no estaban comprometidos y ahora eran gratis:

| Item | Before | After | |-------------------------------|------------|-----------| | Commit Charge (K) | 15,516,388 | 7,264,420 | | Physical Memory Available (K) | 1,959,480 | 9,990,012 | | Zeroed Paging List (K) | 539,212 | 8,556,340 |

Nota: Es algo interesante que Windows perdería el tiempo instantáneamente poniendo a cero toda la memoria, en lugar de simplemente ponerla en una lista de espera, y la pondrá a cero según sea necesario (ya que las solicitudes de memoria deben satisfacerse).

Ninguna de esas cosas explica lo que estaba haciendo la RAM (¡¿Qué estás haciendo simplemente sentada allí? ¡¿Qué contiene ?!)

¡Qué hay en esa memoria!

Esa memoria RAM debe contener algo útil; debe tener algun proposito Para eso me dirigí a RAMMap de SysInternals . Puede desglosar las asignaciones de memoria.

La única pista que proporciona RAMMap es que los 8 GB de memoria física se asociaron con algo llamado Session Private . Estas asignaciones privadas de sesión no están asociadas con ningún proceso (es decir, no es mi proceso):

| Item | Before | After | |------------------------|----------|----------| | Session Private | 8,031 MB | 276 MB | | Unused | 1,111 MB | 8,342 MB |

Ciertamente no estoy haciendo nada con EMS, XMS, AWE, etc.

¿Qué podría estar sucediendo en una aplicación de 32 bits, sin administrador, que está causando que Windows asigne 7 GB de RAM adicionales?

  • No es un caché de elementos intercambiados
  • no es un caché de SuperFetch

Es justo allí ; RAM de consumo.

Sesión privada

La única información sobre la memoria de "sesión privada" es de una publicación de blog que anuncia RAMMap :

Sesión privada: memoria que es privada para una sesión particular en sesión. Esto será más alto en los servidores Host de sesión RDS.

¿Qué tipo de aplicación es esta?

Esta es una aplicación de Windows nativa de 32 bits (es decir, no Java, no .NET). Como es una aplicación nativa de Windows, por supuesto, hace un uso intensivo de la API de Windows.

Cabe señalar que no estaba pidiendo a la gente que depurara la aplicación; Esperaba que un desarrollador de Windows supiera por qué Windows podría tener memoria que nunca asigné. Dicho esto, lo único que cambió recientemente (en los últimos 2 o 3 años) que podría causar tal cosa es la función que toma una captura de pantalla cada 5 minutos y la guarda en la carpeta %LocalAppData% del usuario. Un temporizador se dispara cada cinco minutos:

QueueUserWorkItem(TakeScreenshotThreadProc);

Y pseudocódigo del método de hilo:

void TakeScreenshotThreadProc(Pointer data) { String szFolder = GetFolderPath(CSIDL_LOCAL_APPDTA); ForceDirectoryExists(szFolder); String szFile = szFolder + "/" + FormatDateTime(''yyyyMMdd"_"hhnnss'', Now()) + ".jpg"; Image destImage = new Image(); try { CaptureDesktop(destImage); JPEGImage jpg = new JPEGImage(); jpg.CopyFrom(destImage); jpg.CompressionQuality = 13; jpg.Compress(); HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, null, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_ENCRYPTED, 0); //error checking elucidated try { Stream stm = new HandleStream(hFile); try { jpg.SaveToStream(stm); } finally { stm.Free(); } } finally { CloseHandle(hFile); } } finally { destImage.Free(); } }