Compartir vía


Procedimientos recomendados para administrar el uso de RAM en aplicaciones de alto nivel

Aunque el sistema operativo Azure Sphere usa el kernel de Linux como base, es importante recordar que todavía está escribiendo aplicaciones para un dispositivo incrustado con restricciones significativas de RAM. Aplicar buenas prácticas de programación incrustadas le ayudará a crear aplicaciones de Azure Sphere confiables.

Importante

Para obtener información de uso de RAM precisa para la aplicación, es importante que ejecute la aplicación sin depurar. La ejecución de la aplicación en el depurador provocará un uso inflado de la RAM, ya que la RAM consumida por el servidor de depuración se incluirá en las estadísticas de uso de RAM notificadas. Para obtener más información sobre las estadísticas de memoria para aplicaciones que se ejecutan en el dispositivo conectado, consulte Uso de memoria en aplicaciones de alto nivel.

Estos son algunos procedimientos recomendados a seguir:

  • Asigne memoria por adelantado (idealmente estáticamente) y déjela asignada durante la vida útil de la aplicación siempre que sea posible. Esto aumentará enormemente el determinismo del uso de RAM de la aplicación y reducirá el riesgo de aumentos y fragmentación de la superficie de memoria durante la vida útil de la aplicación.
  • Cuando la asignación dinámica es absolutamente necesaria:
    • Intente minimizar la frecuencia de asignaciones de memoria de montón y desasignaciones que realiza la aplicación para reducir los riesgos de fragmentación de memoria de montón, por ejemplo, aprovechando las técnicas de asignación de fragmentos/grupo de memoria.
    • Revise las páginas apiladas y, cuando sea posible, ajuste las llamadas a malloc() con llamadas para memset() forzar la confirmación de las páginas. Esto ayuda a garantizar que, si una asignación hace que la aplicación supere el límite de RAM, el sistema operativo la cerrará de forma inmediata y predecible. Esperar al acceso asignado páginas introducirá el riesgo de un retraso en el bloqueo de memoria, que es más difícil reproducir y diagnosticar.
    • Habilita el seguimiento de asignación de memoria de pila en el modo de desarrollo.
  • Evite usar Log_Debug cadenas grandes y quite estas llamadas (por ejemplo, con un #ifdef) cuando no esté en modo de desarrollo. Log_Debug hace que se asignen búferes temporales, llevando a ráfagas repentinas en el uso de RAM cuando se usa con cadenas grandes.
  • Use la API EventLoop siempre que sea posible para tareas asincrónicas periódicas (como interactuar con periféricos) en lugar de crear subprocesos. La creación de subprocesos hace que el kernel de Linux asigne memoria adicional atributo a la aplicación. Esto reduce el determinismo de la aplicación, ya que aumenta la probabilidad de que el programador del sistema operativo cambie entre varias operaciones distintas que pueden provocar que la aplicación supere el límite de RAM. Muchas de las aplicaciones de Azure Sphere Sample, como la GPIO_HighLevelApp, demuestran cómo usar EventLoop.
  • Evite el uso prematuro de cachés de memoria para los valores que se pueden volver a calcular en tiempo de ejecución.
  • Al usar libcurl:
    • Ajuste los tamaños máximos del búfer de socket al usar libcurl. Azure Sphere OS asignará búferes de socket que se atribuyen al uso de RAM de la aplicación. Reducir estos tamaños de búfer puede ser una buena manera de reducir la superficie de RAM de la aplicación. Tenga en cuenta que hacer los búferes de socket demasiado pequeños afectará negativamente al rendimiento de libcurl. En su lugar, ajuste los tamaños máximos de búfer para su escenario:

          static int sockopt_callback(void* clientp, curl_socket_t curlfd, curlsocktype purpose)
          {
              int size = /*specify max buffer sizes here (in bytes)*/
              int size_size = sizeof(size);
              setsockopt(curlfd, SOL_SOCKET, SO_SNDBUF, &size, &size_size);
              setsockopt(curlfd, SOL_SOCKET, SO_RCVBUF, &size, &size_size);
              return CURL_SOCKOPT_OK;
          }
      
          // Place the following along with other calls to curl_easy_setopt
          curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, &sockopt_callback);
      

      Consulta la documentación CURLOPT_SOCKOPTFUNCTION libcurl.

      • Los parámetros de nivel superior CURLOPT_BUFFERSIZE y CURLOPT_UPLOAD_BUFFERSIZE pueden ajustarse de forma similar.

      • Libcurl también admite la invalidación de sus funciones de memoria interna mediante el uso curl_global_init_mem y el paso de funciones de devolución de llamada para malloc, free, realloc, strdupy calloc. Esta funcionalidad le permite realizar un seguimiento de las asignaciones dinámicas o incluso alterar el comportamiento. Por ejemplo, podría asignar un grupo de memoria por adelantado y, a continuación, usar estas devoluciones de llamada para asignar la memoria libcurl de ese grupo. Esta puede ser una técnica eficaz para configurar barandillas y aumentar el determinismo de su aplicación. Consulte la documentación curl_global_init_mem libcurl para obtener más información sobre cómo usar estas devoluciones de llamada.

        Nota

        Este mecanismo de devolución de llamada no cubre todas las asignaciones de memoria causadas por libcurl, solo las realizadas directamente por libcurl. En concreto, las asignaciones realizadas por wolfSSL por debajo no son rastreadas.