Freigeben über


Bewährte Methoden für die Verwaltung der RAM-Nutzung in allgemeinen Anwendungen

Obwohl das Azure Sphere-Betriebssystem den Linux-Kernel als Basis verwendet, ist es wichtig, daran zu denken, dass Sie weiterhin Anwendungen für ein eingebettetes Gerät mit erheblichen RAM-Einschränkungen schreiben. Wenn Sie bewährte Methoden für die eingebettete Programmierung anwenden, können Sie zuverlässige Azure Sphere-Anwendungen erstellen.

Wichtig

Um genaue Ram-Nutzungsinformationen für Ihre Anwendung zu erhalten, ist es wichtig, dass Sie Ihre App ohne Debuggen ausführen. Das Ausführen Ihrer App unter dem Debugger führt zu einer überhöhten RAM-Auslastung, da der vom Debugserver verbrauchte RAM in den gemeldeten RAM-Nutzungsstatistiken enthalten ist. Weitere Informationen zu Speicherstatistiken für Anwendungen, die auf dem angeschlossenen Gerät ausgeführt werden, finden Sie unter Arbeitsspeichernutzung in allgemeinen Anwendungen.

Hier sind einige bewährte Methoden, die Sie befolgen sollten:

  • Ordnen Sie Arbeitsspeicher im Voraus (idealerweise statisch) zu, und lassen Sie ihn nach Möglichkeit für die Lebensdauer Ihrer Anwendung zugeordnet. Dies erhöht die Determinität der RAM-Nutzung Ihrer Anwendung erheblich und verringert das Risiko, dass der Speicherbedarf über die Lebensdauer Ihrer Anwendung zunimmt und fragmentiert wird.
  • Wenn die dynamische Zuordnung unbedingt erforderlich ist:
    • Versuchen Sie, die Häufigkeit von Heap-Speicherbelegungen und -freigaben zu minimieren, die von der Anwendung ausgeführt werden, um das Risiko der Heapspeicherfragmentierung zu verringern, z. B. durch Die Nutzung von Segmentzuordnungs-/Speicherpooltechniken.
    • Überprüfen Sie Stapelseiten, und umschließen Sie Aufrufe von malloc() nach Möglichkeit mit Aufrufen von memset() , um den Commit von Seiten zu erzwingen. Dadurch wird sichergestellt, dass das Betriebssystem diese sofort und vorhersagbar beendet, wenn eine Zuordnung dazu führt, dass ihre Anwendung den RAM-Grenzwert überschreitet. Das Warten auf den Zugriff auf zugeordnete Seiten führt zu einem verzögerten Absturz von nicht genügend Arbeitsspeicher, der schwieriger zu reproduzieren und zu diagnostizieren ist.
    • Aktivieren Sie die Nachverfolgung der Heapspeicherbelegung im Entwicklungsmodus.
  • Vermeiden Sie die Verwendung mit Log_Debug großen Zeichenfolgen, und entfernen Sie diese Aufrufe (z. B. mit einem #ifdef), wenn sie sich nicht im Entwicklungsmodus befinden. Log_Debug bewirkt, dass temporäre Puffer zugeordnet werden, was bei verwendung mit großen Zeichenfolgen zu plötzlichen Bursts bei der RAM-Nutzung führt.
  • Verwenden Sie die EventLoop-API nach Möglichkeit für regelmäßige asynchrone Aufgaben (z. B. die Interaktion mit Peripheriegeräten), anstatt Threads zu erstellen. Das Erstellen von Threads bewirkt, dass der Linux-Kernel zusätzlichen Speicher zuweist, der Ihrer Anwendung zugeordnet ist. Dies reduziert den Determinismus Ihrer App, da die Wahrscheinlichkeit erhöht wird, dass der Betriebssystemplaner zwischen mehreren, unterschiedlichen Vorgängen wechselt, die dazu führen können, dass Ihre Anwendung den RAM-Grenzwert überschreitet. Viele der Azure Sphere-Beispielanwendungen, z . B. die GPIO_HighLevelApp, veranschaulichen die Verwendung von EventLoop.
  • Vermeiden Sie die vorzeitige Verwendung von Speichercaches für Werte, die zur Laufzeit neu berechnet werden können.
  • Bei Verwendung von libcurl:
    • Optimieren Sie die maximalen Socketpuffergrößen bei Verwendung von libcurl. Das Azure Sphere-Betriebssystem ordnet Socketpuffer zu, die der RAM-Nutzung Ihrer Anwendung zugeordnet werden. Das Reduzieren dieser Puffergrößen kann eine gute Möglichkeit sein, den RAM-Speicherbedarf Ihrer Anwendung zu reduzieren. Beachten Sie, dass zu kleine Socketpuffer die Leistung von libcurl beeinträchtigen. Optimieren Sie stattdessen die maximalen Puffergrößen für Ihr Szenario:

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

      Weitere Informationen finden Sie in der CURLOPT_SOCKOPTFUNCTION libcurl-Dokumentation.

      • Die übergeordneten CURLOPT_BUFFERSIZE - und CURLOPT_UPLOAD_BUFFERSIZE-Parameter können auf ähnliche Weise optimiert werden.

      • Libcurl unterstützt auch das Überschreiben der internen Speicherfunktionen durch Verwendung curl_global_init_mem und Übergabe von Rückruffunktionen für malloc, , freerealloc, strdupund calloc. Mit dieser Funktion können Sie dynamische Zuordnungen nachverfolgen oder sogar das Verhalten ändern. Beispielsweise können Sie vorab einen Speicherpool zuordnen und dann diese Rückrufe verwenden, um libcurl-Arbeitsspeicher aus diesem Pool zuzuweisen. Dies kann eine effektive Technik sein, um Schutzmaßnahmen festzulegen und den Determinismus Ihrer Anwendung zu erhöhen. Weitere Informationen zur Verwendung dieser Rückrufe finden Sie in der curl_global_init_mem libcurl-Dokumentation.

        Hinweis

        Dieser Rückrufmechanismus deckt nicht alle Speicherbelegungen ab, die durch libcurl verursacht werden, nur solche, die direkt von libcurl selbst vorgenommen werden. Insbesondere werden zuordnungen, die von wolfSSL darunter vorgenommen werden, nicht nachverfolgt.