Partage via


Bonnes pratiques pour la gestion de l’utilisation de la RAM dans les applications de haut niveau

Bien que le système d’exploitation Azure Sphere utilise le noyau Linux comme base, il est important de se rappeler que vous écrivez toujours des applications pour un appareil incorporé avec des contraintes de RAM importantes. L’application de bonnes pratiques de programmation incorporée vous aidera à créer des applications Azure Sphere fiables.

Important

Pour obtenir des informations précises sur l’utilisation de la RAM pour votre application, il est important d’exécuter votre application sans débogage. L’exécution de votre application sous le débogueur entraîne une augmentation de l’utilisation de la RAM, car la RAM consommée par le serveur de débogage sera incluse dans les statistiques d’utilisation de la RAM signalées. Pour plus d’informations sur les statistiques de mémoire pour l’application s’exécutant sur l’appareil attaché, consultez Utilisation de la mémoire dans les applications de haut niveau.

Voici quelques bonnes pratiques à suivre :

  • Allouez de la mémoire à l’avance (idéalement de manière statique) et laissez-la allouée pendant la durée de vie de votre application dans la mesure du possible. Cela augmentera considérablement le déterminisme de l’utilisation de la RAM de votre application et réduira le risque d’augmentation de l’empreinte mémoire et de fragmentation sur la durée de vie de votre application.
  • Lorsque l’allocation dynamique est absolument nécessaire :
    • Essayez de réduire la fréquence des allocations et des désallocations de mémoire du tas effectuées par l’application afin de réduire les risques de fragmentation de la mémoire du tas, par exemple, en tirant parti des techniques d’allocation de segments/pool de mémoire.
    • Passez en revue les pages de pile et, si possible, encapsulez les appels à malloc() avec des appels à memset() pour forcer la validation des pages. Cela permet de s’assurer que si une allocation entraîne le dépassement de la limite de ram de votre application, le système d’exploitation l’arrêtera immédiatement et de manière prévisible. L’attente d’accéder aux pages allouées introduit le risque d’un blocage de mémoire insuffisante retardé, qui est plus difficile à reproduire et à diagnostiquer.
    • Activez le suivi de l’allocation de mémoire du tas en mode développement.
  • Évitez d’utiliser Log_Debug avec des chaînes volumineuses et supprimez ces appels (par exemple, avec un #ifdef) quand vous n’êtes pas en mode développement. Log_Debug provoque l’allocation de mémoires tampons temporaires, ce qui entraîne des pics soudains d’utilisation de la RAM lorsqu’ils sont utilisés avec des chaînes volumineuses.
  • Utilisez l’API EventLoop autant que possible pour les tâches asynchrones périodiques (telles que l’interaction avec les périphériques) au lieu de créer des threads. La création de threads entraîne l’allocation de mémoire supplémentaire par le noyau Linux à votre application. Cela réduit le déterminisme de votre application, car il augmente la probabilité que le planificateur de système d’exploitation bascule entre plusieurs opérations distinctes qui peuvent entraîner le dépassement de la limite de RAM de votre application. La plupart des exemples d’applications Azure Sphere, telles que la GPIO_HighLevelApp, montrent comment utiliser l’EventLoop.
  • Évitez l’utilisation prématurée des caches de mémoire pour les valeurs qui peuvent être recalculées lors de l’exécution.
  • Lors de l’utilisation de libcurl :
    • Ajustez les tailles maximales de mémoire tampon de socket lors de l’utilisation de libcurl. Le système d’exploitation Azure Sphere alloue des mémoires tampons de socket qui sont attribuées à l’utilisation de la RAM de votre application. La réduction de ces tailles de mémoire tampon peut être un bon moyen de réduire l’encombrement ram de votre application. Notez que le fait de rendre les mémoires tampons de socket trop petites aura un impact négatif sur les performances de libcurl. Au lieu de cela, réglez les tailles maximales de mémoire tampon pour votre scénario :

          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);
      

      Consultez la documentation CURLOPT_SOCKOPTFUNCTION libcurl.

      • Les paramètres de CURLOPT_BUFFERSIZE et de CURLOPT_UPLOAD_BUFFERSIZE de niveau supérieur peuvent être réglés de la même façon.

      • Libcurl prend également en charge la substitution de ses fonctions de mémoire interne en utilisant curl_global_init_mem et en transmettant des fonctions de rappel pour malloc, free, reallocstrdup, et calloc. Cette fonctionnalité vous permet de suivre les allocations dynamiques ou même de modifier le comportement. Par exemple, vous pouvez allouer un pool de mémoire à l’avance, puis utiliser ces rappels pour allouer de la mémoire libcurl à partir de ce pool. Il peut s’agir d’une technique efficace pour définir des garde-fous et augmenter le déterminisme de votre application. Pour plus d’informations sur l’utilisation de ces rappels, consultez la documentation curl_global_init_mem libcurl.

        Note

        Ce mécanisme de rappel ne couvre pas toutes les allocations de mémoire provoquées par libcurl, mais uniquement celles effectuées directement par libcurl lui-même. Plus précisément, les allocations effectuées par wolfSSL en dessous ne sont pas suivies.