다음을 통해 공유


상위 수준 애플리케이션에서 RAM 사용량을 관리하기 위한 모범 사례

Azure Sphere OS는 Linux 커널을 기본으로 사용하지만, RAM 제약 조건이 상당한 포함된 디바이스에 대한 애플리케이션을 계속 작성하고 있다는 점을 기억해야 합니다. 적절한 임베디드 프로그래밍 방법을 적용하면 신뢰할 수 있는 Azure Sphere 애플리케이션을 만드는 데 도움이 됩니다.

중요

애플리케이션에 대한 정확한 RAM 사용 정보를 얻으려면 디버깅 없이 앱을 실행하는 것이 중요합니다. 디버깅 서버에서 사용하는 RAM이 보고된 RAM 사용 통계에 포함되므로 디버거에서 앱을 실행하면 RAM 사용량이 증가합니다. 연결된 디바이스에서 실행되는 애플리케이션에 대한 메모리 통계에 대한 자세한 내용은 상위 수준 애플리케이션의 메모리 사용을 참조하세요.

다음은 따라야 할 몇 가지 모범 사례입니다.

  • 메모리를 미리 할당하고(이상적으로는 정적으로) 가능하면 애플리케이션의 수명 동안 할당된 상태로 둡니다. 이렇게 하면 애플리케이션의 RAM 사용량에 대한 결정성이 크게 증가하고 애플리케이션 수명 동안 메모리 공간이 증가하고 조각화될 위험이 줄어듭니다.
  • 동적 할당이 절대적으로 필요한 경우:
    • 예를 들어 청크 할당/메모리 풀 기술을 활용하여 힙 메모리 조각화의 위험을 줄이기 위해 애플리케이션에서 수행하는 힙 메모리 할당 및 할당 취소 빈도를 최소화해 보세요.
    • 스택 페이지를 검토하고 가능하면 호출을 malloc() 에 대한 호출 memset() 로 래핑하여 페이지를 강제로 커밋합니다. 이렇게 하면 할당으로 인해 애플리케이션이 RAM 제한을 초과하는 경우 OS가 즉시 예측 가능하게 종료됩니다. 할당된 페이지에 액세스하기 위해 대기하면 메모리 부족 충돌이 지연될 위험이 있으므로 재현하고 진단하기가 어렵습니다.
    • 개발 모드에서 힙 메모리 할당 추적 을 사용하도록 설정합니다.
  • 개발 모드가 아닌 경우 큰 문자열과 함께 를 사용하지 Log_Debug 말고 이러한 호출(예: 와 함께)을 #ifdef제거합니다. Log_Debug 을 사용하면 임시 버퍼가 할당되어 큰 문자열과 함께 사용할 때 RAM 사용량이 갑자기 폭발합니다.
  • 스레드를 만드는 대신 주기적인 비동기 작업(예: 주변 장치와 상호 작용)에 대해 가능하면 EventLoop API를 사용합니다. 스레드를 만들면 Linux 커널이 애플리케이션에 특성이 지정된 추가 메모리를 할당합니다. 이렇게 하면 애플리케이션이 RAM 제한을 초과할 수 있는 여러 고유 작업 간에 OS 스케줄러가 전환될 확률이 높아짐에 따라 앱의 결정성이 줄어듭니다. GPIO_HighLevelApp 같은 많은 Azure Sphere 샘플 애플리케이션은 EventLoop을 사용하는 방법을 보여 줍니다.
  • 런타임에서 다시 계산할 수 있는 값에 메모리 캐시를 조기에 사용하지 마세요.
  • libcurl을 사용하는 경우:
    • libcurl을 사용할 때 최대 소켓 버퍼 크기를 조정합니다. Azure Sphere OS는 애플리케이션의 RAM 사용량에 따라 소켓 버퍼를 할당합니다. 이러한 버퍼 크기를 줄이면 애플리케이션의 RAM 공간을 줄이는 좋은 방법이 될 수 있습니다. 소켓 버퍼를 너무 작게 만들면 libcurl의 성능에 부정적인 영향을 줍니다. 대신 시나리오에 대한 최대 버퍼 크기를 조정합니다.

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

      CURLOPT_SOCKOPTFUNCTION libcurl 설명서를 참조하세요.

      • 상위 수준 CURLOPT_BUFFERSIZECURLOPT_UPLOAD_BUFFERSIZE 매개 변수도 비슷하게 조정할 수 있습니다.

      • 또한 Libcurl은 , , freecallocreallocstrdup, 및 에 대한 malloc콜백 함수를 사용하고 curl_global_init_mem 전달하여 내부 메모리 함수 재정의를 지원합니다. 이 기능을 사용하면 동적 할당을 추적하거나 동작을 변경할 수 있습니다. 예를 들어 미리 메모리 풀을 할당한 다음, 이러한 콜백을 사용하여 해당 풀에서 libcurl 메모리를 할당할 수 있습니다. 이는 가드레일을 설정하고 애플리케이션의 결정성을 높이는 효과적인 기술일 수 있습니다. 이러한 콜백을 사용하는 방법에 대한 자세한 내용은 curl_global_init_mem libcurl 설명서를 참조하세요.

        참고

        이 콜백 메커니즘은 libcurl로 인한 모든 메모리 할당을 포함하지 않으며, libcurl 자체에 의해 직접 생성된 메모리 할당만 포함합니다. 특히, 아래 wolfSSL에 의해 만들어진 할당은 추적되지 않습니다.