Sdílet prostřednictvím


Osvědčené postupy pro správu využití paměti RAM v aplikacích vysoké úrovně

Důležité

Toto je dokumentace k Azure Sphere (starší verze). Azure Sphere (starší verze) se vyřazuje 27. září 2027 a uživatelé musí do této doby migrovat do Azure Sphere (integrované). K zobrazení dokumentace k Azure Sphere (integrované) použijte selektor verzí umístěný nad obsahem.

I když operační systém Azure Sphere používá jádro Linuxu jako základ, je důležité si uvědomit, že stále píšete aplikace pro vložené zařízení s významnými omezeními paměti RAM. Použití osvědčených vložených programovacích postupů vám pomůže vytvářet spolehlivé aplikace Azure Sphere.

Důležité

Pokud chcete získat přesné informace o využití paměti RAM pro vaši aplikaci, je důležité, abyste aplikaci spustili bez ladění. Spuštění aplikace pod ladicím programem způsobí nafouknutí využití paměti RAM, protože paměť RAM spotřebovaná ladicím serverem bude zahrnuta do hlášených statistik využití paměti RAM. Další informace o statistikách paměti pro aplikaci spuštěnou na připojeném zařízení naleznete v tématu Použití paměti v aplikacích vysoké úrovně.

Tady je několik osvědčených postupů, které je potřeba dodržovat:

  • Přidělte paměť předem (ideálně staticky) a ponechte ji přidělenou po celou dobu životnosti aplikace, kdykoli je to možné. Tím se výrazně zvýší determinismus využití paměti RAM vaší aplikace a sníží se riziko nárůstu využití paměti a fragmentace po celou dobu života vaší aplikace.
  • Pokud je dynamické přidělování naprosto nezbytné:
    • Pokuste se minimalizovat frekvenci přidělení paměti haldy a uvolnění, které aplikace provádí, aby se snížila rizika fragmentace paměti haldy, například pomocí technik přidělení bloků dat nebo fondu paměti.
    • Zkontrolujte stránky zásobníku a pokud je to možné, zabalte volání malloc() volání, která memset() vynutí potvrzení stránek. To pomáhá zajistit, že pokud přidělení způsobí, že vaše aplikace překročí limit paměti RAM, operační systém ho okamžitě a předvídatelně ukončí. Čekání na přístup k přiděleným stránkám způsobí riziko opožděného chybového ukončení nedostatku paměti, což je obtížnější reprodukovat a diagnostikovat.
    • Povolte sledování přidělování paměti haldy v režimu vývoje.
  • Vyhněte se použití Log_Debug s velkými řetězci a odeberte tato volání (například s ) #ifdefv případě, že nejsou ve vývojovém režimu. Log_Debug způsobí přidělení dočasných vyrovnávacích pamětí, což vede k náhlému nárůstu využití paměti RAM při použití s velkými řetězci.
  • Rozhraní EventLoop API používejte vždy, když je to možné pro pravidelné asynchronní úlohy (například interakci s periferními zařízeními) místo vytváření vláken. Vytvoření vláken způsobí, že jádro Linuxu přidělí vaší aplikaci další paměť. Tím se sníží determinismus vaší aplikace, protože zvyšuje pravděpodobnost přepínání plánovače operačního systému mezi několika různými operacemi, které můžou způsobit překročení limitu paměti RAM vaší aplikace. Mnoho ukázkových aplikací Azure Sphere, jako je například GPIO_HighLevelApp, ukazuje, jak používat EventLoop.
  • Vyhněte se předčasnému použití mezipamětí paměti pro hodnoty, které je možné přepočíst za běhu.
  • Při použití knihovny libcurl:
    • Při použití knihovny libcurl vylaďte maximální velikosti vyrovnávací paměti soketů. Operační systém Azure Sphere přidělí vyrovnávací paměti soketů, které jsou přiřazeny k využití paměti RAM vaší aplikace. Snížení těchto velikostí vyrovnávací paměti může být dobrým způsobem, jak snížit nároky paměti RAM vaší aplikace. Mějte na paměti, že příliš malé vyrovnávací paměti soketů nepříznivě ovlivní výkon libcurl. Místo toho vylaďte maximální velikosti vyrovnávací paměti pro váš scénář:

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

      Viz dokumentace CURLOPT_SOCKOPTFUNCTION libcurl.

      • Parametry vyšší úrovně CURLOPT_BUFFERSIZE a CURLOPT_UPLOAD_BUFFERSIZE lze podobně ladit.

      • Libcurl také podporuje přepsání vnitřních paměťových funkcí pomocí curl_global_init_mem a předávání funkcí zpětného volání pro malloc, , freerealloc, strdup, a calloc. Tato funkce umožňuje sledovat dynamické přidělování nebo dokonce měnit chování. Například můžete předem přidělit fond paměti a pak pomocí těchto zpětných volání přidělit paměť libcurl z tohoto fondu. Může to být účinná technika nastavení mantinely a zvýšení determinismu vaší aplikace. Další informace o použití těchto zpětných volání najdete v dokumentaci curl_global_init_mem libcurl.

        Poznámka:

        Tento mechanismus zpětného volání nepokrývá všechny přidělení paměti způsobené knihovnou libcurl, pouze ty, které provádí přímo samotný libcurl. Konkrétně nejsou sledovány přidělení vlkSSL pod ním.