버전
menu_open
Wwise SDK 2023.1.3
메모리 사용량을 줄이는 방법

원하는 한도에 맞추어 메모리 사용량을 줄이는 것은 꽤나 어려운 일일 것입니다. 다음은 메모리 사용을 줄이는 데 도움이 되는 방법들입니다.

오브젝트 메모리

오브젝트 메모리 사용은, 메모리 내에 불러오는 사운드와 이벤트 개수 및 게임 오브젝트의 양에 따라 직접적인 영향을 받습니다. 오브젝트 메모리는 사운드 디자인의 작동을 구현하기 위해 프로젝트 안에 들어있는 오브젝트들의 모든 속성을 포함합니다. 여기에는 또한 모든 게임 오브젝트와 연관된 정보(게임 싱크 값, 위치, 방향, 등)도 포함돼있습니다. 더 많은 뱅크를 불러올수록 더 많은 메모리가 할당돼야 합니다. 이때 필요한 메모리 크기는, 하나의 시나리오, 레벨, 맵, 게임 영역 등과 같은 환경에서 재생될 사운드의 개수에 대해서만 영향을 받습니다. 이러한 할당을 줄이는 데 도움이 되는 방법이 있습니다.

  • 큰 SoundBank를 여러 개의 사운드 구조체와 Event로 쪼개 작은 SoundBank에 넣기. 참고로 Advanced Profiler의 SoundBanks 탭에 있는 Object Memory 열을 보면 각각의 SoundBank가 차지하고 있는 메모리를 확인할 수 있습니다. 그러면 필요에 따라 SoundBank를 동적으로 로드/언로드할 수 있습니다. SoundBank를 쪼갤 때에는 전략적으로 접근하도록 하세요. 예를 들어, 대사 SoundBank를 나눌 때에는 한 캐릭터의 모든 대사 한줄 한줄을 하나씩 생성하지 않도록 합니다. 대신, 문맥을 보고 대사들을 그룹짓는 것이 좋습니다.
  • AK::SoundEngine::ExecuteActionOnEvent API를 사용해 이벤트 개수 줄이기. Play/Stop 한 쌍은 하나의 Play 이벤트 및 Stop과 Pause/Resume의 ExecuteActionOnEvent 호출로 대체할 수 있습니다 (동일한 Play 이벤트가 될 수도 있음).
  • 게임 오브젝트를 철저하게 관리하기. 오브젝트의 역할이 끝나는 대로 이 오브젝트의 등록을 해제하세요. 사용하지 않은 게임 오브젝트가 포함된 풀이 활성화되어 있지 않도록 방지하세요. 이러한 풀을 활성화한 상태로 두는 것은 전혀 이득이 없으며 메모리를 소비할 수 있습니다. 예를 들어 NPC 하나가 죽을 경우를 생각해봅시다. 해당 게임 오브젝트를 등록 해제하고 이를 다른 곳에 재사용하지 않습니다. 필요시 새로운 게임 오브젝트를 등록합니다. 일반적으로, 활성화된 게임 오브젝트가 수천 개에 달한다면 너무 많다고 할 수 있습니다.
  • 사운드를 정리할 목적만으로 Actor-Mixer를 사용하지 않기. 폴더와 Work Unit은 메모리를 차지하지 않지만, Actor-Mixer는 메모리를 차지합니다. 단, 기본 설정이 아닌 비슷한 속성들을 공유할 경우에는 이 속성이 한 번만 존재하므로 메모리를 절약할 수 있습니다. 물론, 이 때 Actor-Mixer가 이벤트에 의해 참조되는지에 따라 달라질 수 있습니다 (예: SetVolume이나 SetPitch).
  • 큰 계층 구조의 크기와 복잡성 줄이기. 'Impact' 계층 구조나 'Footstep' 계층 구조같은 것들이 크기가 큰 계층 구조의 흔한 예입니다. 변수가 많기 때문에 크기가 커질 수 있고 구조에 많은 메모리를 사용할 수 있습니다. 다음은 이러한 계층 구조를 감소할 수 있는 몇 가지 방법입니다.
    • Switch 내 변경되는 것이 단순히 속성뿐일 경우 (동일 샘플에 다른 볼륨/피치/랜더마이저, 등 사용) RTPC를 이용합니다.
    • Switch Container 계층 구조를 여러 뱅크로 쪼갭니다. SoundBank Manager에서 Switch 컨테이너를 포함시킬 경우 그에 따른 모든 하위 구조 또한 포함됩니다. 그러나 SoundBank Editor 뷰에서 Game Sync 탭이나 Edit 탭을 이용하면 수동으로 일부 하위 구조를 제외시킬 수 있습니다. 예를 들어 'Footstep' 계층 구조에서 첫 Switch 변수가 Surface Type인 경우가 있습니다. 서로 다른 SoundBank의 Switch를 쪼개 맥락에 맞게 불러옵니다. 도시 환경의 콘크리트나 금속 계단과 같이 게임 전반에서 사용될 표면을 포함하고 있는 주요 'Footstep' SoundBank를 만들 수도 있고, 진흙과 같이 게임의 한 특정 장면/영역에서만 사용되는 특정 표면의 맥락적 SoundBank를 만들 수도 있습니다.
  • '외부 음원'을 사용해 Wwise Actor-Mixer 계층 구조만큼 많은 제어가 필요하지 않은 사운드의 오버헤드를 줄이기. 이 방법은 주로 보이스오버(voice-over)에 적합합니다.

Processing 메모리

Processing 카테고리의 메모리는 사운드를 재생하는 데 사용됩니다. 여기에는 오디오 음원을 압축 해제하고 효과를 적용하며 믹싱하는 데 필요한 버퍼가 포함돼있습니다. 이 메모리는 동시에 재생하는 사운드의 개수에 영향을 받습니다. 또한 동시에 사용되는 효과의 개수와 유형에도 영향을 받습니다. 이를 줄이려면 자신의 게임에서 한 번에 몇 개의 사운드가 들리도록 할 것인지를 곰곰이 생각해보는 것이 좋습니다. 어떤 게임의 시나리오는 사운드 10 개조차 드물게 들리도록 할 수 있지만, 또 다른 게임에서는 수백 개가 넘어갈 수도 있습니다. 이 때 최악의 상황을 고려해야 합니다.

참고로 일부 게임(Xbox One)을 프로파일링해본 결과 다음과 같은 수치가 나왔습니다.

  • 1 MB로 대략 42 보이스를 재생할 수 있습니다.
  • 2 MB로 대략 96 보이스를 재생할 수 있습니다. 대부분 정비례로 증가하지만 어느 코덱을 사용하는지, 효과는 얼마나 적용했는지 등, 다양한 요소에 따라 크게 달라질 수 있습니다. 예를 들어 Vorbis 코덱을 쓰면 품질 설정에 따라 보이스 당 약 50% 정도의 메모리를 더 사용합니다. 만약 한 번에 재생되는 사운드가 170 개라면, 아마 그다지 현명한 선택이 아닐 것이고 제대로 사용할 수도 없을 것입니다. 그러나 자신의 게임에 이상적인 실제 보이스 개수를 파악하려면 다소간의 실험을 거쳐야 할 것입니다. Profiler의 Memory 탭을 이용해 자신의 게임에 적용할 여러 시나리오를 검토해보고 리소스를 얼마나 차지하는지 확인하세요.

처리에 사용되는 메모리를 줄이려면 동시 보이스 개수를 줄여야 합니다. 이는 다음과 같은 방법으로 처리할 수 있습니다.

  • 재생 한도 (Advanced Settings). 예를 들어, 꼭 총알 50 개가 튀어나오는 소리를 들어야 할까요? 그러면 이 사운드를 15개 정도로 제한해볼 수 있습니다.
    참고: 버스에도 한도를 설정할 수 있습니다.
  • 우선 순위 (Advanced Settings). 예를 들어, 총알 소리는 대사보다 덜 중요할 수 있죠. 너무 많은 소리가 재생될 땐 총알 소리를 먼저 제거할 수 있습니다. Playback Limits과 함께 사용하세요.
  • 거리 기반 우선 순위 상쇄값 (Advanced Settings). 멀리 떨어진 오브젝트는 가까이 위치한 오브젝트보다 중요하지 않습니다. 총알의 경우를 다시 예로 들어봅시다. 가까이에서 15개의 총알이 들리는 와중에는 10 미터 밖의 총 소리를 들을 필요는 없습니다.
  • Below Threshold Behavior (한계점 이하의 경우 행동) (Advanced Settings). 가장 저렴한 방법은 (CPU 및 메모리) 'Kill Voice'이며, 반복 재생되지 않는 사운드에 유용합니다. 두 번째로 자주 사용되는 선택 사항은 'Send To Virtual' 'Play from beginning (처음부터 재생)', 그리고 'Send To Virtual' 'Resume (다시 재생)', 다음으로 'Send To Virtual' 'Play from elapsed time (경과한 시간부터 재생)'입니다. 'Continue to play (계속 재생)'과 'Play from elapsed time (경과한 시간부터 재생)'이 가장 비용이 높은 옵션이며, Wwise의 기본값은 'Continue To Play'입니다.
  • Volume Threshold (볼륨 한계점) (Project Settings). 이 방법은 너무 작아서 잘 들리지 않는 소리를 없애는 데 유용합니다. 이는 Below Threshold Behavior 및 Attenuation 설정 내용과 밀접하게 연관되어 작동합니다 (주로 멀리 있는 소리일 수록 더 잘 들리지 않음).
    참고: 볼륨 한계점을 런타임에 프로그래밍으로 변경할 수 있습니다. 이 방법은 많은 처리를 요하는 게임 장소에서 사용하면 더 많은 보이스를 'under volume threshold (볼륨 한계점 이하)' 상태로 보낼 수 있습니다.
  • 사용된 코덱 설정 변경 (Conversion Settings). Vorbis는 오디오를 압축 해제하는 데 별도의 추가 메모리가 필요합니다. 다양한 매개 변수는 필요한 메모리 양을 늘리거나 줄일 수 있습니다. 그러나 적절한 균형을 잘 고려해야 합니다. 다른 코덱을 사용하거나 낮은 압축 비율을 사용하면 Processing 메모리 로드 시간을 줄일 수 있지만, 대신 로드된 뱅크 안에 있는 큰 파일들의 메모리 사용량이 늘어나게 됩니다. 때에 따라서는, Processing 메모리 사용량에 500 KB 정도가 더 있어야 Media용 메모리 몇 MB를 확보해놓을 수 있어, 이는 곧 전체 오디오 가용량을 확보할 수 있게 됩니다.
  • 적거나 낮은 품질. 일부 효과는 처리하는 데 많은 메모리가 필요합니다. 가장 흔하게 메모리를 잡아먹는 것은 다양한 형태로 사용되는 Reverb 효과입니다. 사실 한 게임 안에서 동시에 작동하는 잔향의 수는 몇 개만 있는 것이 좋습니다. 일반적으로 4개 이하를 권고합니다. 또한 잔향의 품질이나 길이를 줄이는 것도 도움이 됩니다.

미디어 메모리 (SoundBanks)

SoundBank가 차지하는 메모리의 양은 대부분 포함된 사운드 데이터에 의해 결정됩니다. 자신의 미디어가 사용하는 메모리 양은 다음과 같은 방식으로 제어할 수 있습니다.

  • 큰 SoundBank를 여러 개의 사운드 구조와 Event로 쪼개 작은 SoundBank에 넣기. 필요에 따라 동적으로 로딩 또는 언로딩합니다.
  • 디스크로부터 더 많은 사운드를 스트리밍하기 (사운드의 속성). 레이턴시에 민감한 사운드는 미리 로드될 수 있는 프리패치 미디어를 사용할 수 있으며, 필요시 PinEventInStreamCache API를 사용해 캐시로 스트리밍될 수 있습니다.
  • PrepareEvent() API 사용하기.
  • 오디오를 더 압축하기 (Conversion Settings, 코덱, 등).
  • 낮은 샘플 레이트 사용하기. 또한 Conversion Settings의 Automatic Sample Rate Detection 기능을 참고하세요.
  • Replacing wind-type sounds with a Soundseed Wind/Woosh plug-in equivalent. 바람 앰비언스는 오랫동안 반복 재생되는 경우가 많으므로 미디어 공간을 많이 차지할 수 있습니다. 이 플러그인으로 휙 소리를 내는 칼날이나 프로펠러, 열린 차창으로 불어오는 바람, 환풍기 소음, 등을 모델링할 수 있습니다. 어떤 소음도 모델링할 수 있어 바람이 아닌 응용 환경 또한 고려 대상입니다. 예: 바닷가의 파도나 멀리서 들리는 고속도로 소음

Tuning "Temp Alloc" Memory

Wwise uses an internal pool of memory to manage some temporary allocations that persist for less than one audio-render tick, which are represented in the Advanced Profiler's Memory tab as "Temp Alloc". These temporary allocations exist for a specific amount of time, have very little overhead, are handled internally by the sound engine, and cannot be forwarded to developer-provided memory allocation hooks. Instead, the only allocations in this regard that are observed by the Advanced Profiler and memory allocation hooks are the larger memory blocks that the temporary allocations are made from. Therefore, it might be desirable to manually tune the management of "Temp Alloc" memory blocks, in order to better optimize memory usage in your game.

During AK::MemoryMgr::Init, AkMemSettings::tempAllocSettings controls the behavior of the memory blocks for each Temp Alloc category. Notably, this includes configuring the size of the memory blocks, the minimum number of blocks that the system keeps allocated at all times, and how many blocks have to be unused for a tick before the system starts freeing memory. You can use AK::GetTempAllocStats() to see how much memory the Temp Alloc system uses in your game at runtime, and better fine tune configuration of the system.

The following are some suggestions depending on your game's requirements, or other behavior observed during profiling:

  • If you are not concerned about the overhead of allocating and freeing the memory blocks, or the memory fragmentation that is incurred when the memory blocks are freed, it might be desirable to set AK::TempAllocInitSettings::uMinimumBlockSize to a lower value than the default, so that it better matches the memory usage of your game's needs at any given time.
  • If the allocation and freeing of blocks causes excessive memory fragmentation, you can measure AK::TempAllocStats::uPeakMemUsed to view the Temp Alloc system's peak memory usage, and then ensure that the AK::TempAllocInitSettings::uMinimumBlockCount is set to a high enough value so that all of the blocks you might use are allocated when the sound engine is initialized, and never freed afterward.
  • If you want to avoid freeing memory blocks without evaluating your peak memory usage, you can set AK::TempAllocInitSettings::uMaximumUnusedBlocks to a high value to ensure that the system can allocate new blocks, but not free them, even during periods of low memory load.
  • If you are using the Job Manager for audio rendering, as described in Leveraging the Job Manager for Concurrent Execution of Audio Rendering Jobs, the number of memory blocks will increase. This is because the memory blocks are all thread-local, and one memory block is typically allocated by each active worker. It might be desirable to lower AK::TempAllocInitSettings::uMinimumBlockSize so that using more workers does not cause a significant increase in used memory in your game.
  • If your memory allocation system includes some metadata adjacent to large memory allocations, it might be worth ensuring that the amount of memory allocated by the memory blocks does not cause a significant amount of waste. Given a requested allocation of 2048 KiB, some memory allocation systems might actually map 2112 KiB of memory. However, a requested allocation might of 2047 KiB would map 2048 KiB of memory. The block sizes do not need to be powers of two, or exactly matched to page sizes, so it might be preferable to set AK::TempAllocInitSettings::uMinimumBlockSize to a slightly reduced value than intended in order to mitigate waste in this regard.

Some debugging options are available in AK::TempAllocInitSettings. In the Debug and Profile configuration of the sound engine, AK::TempAllocInitSettings::bDebugDetailedStats and AK::TempAllocInitSettings::bDebugEnableSentinels are enabled by default in order to improve tracking of usage statistics, and to provide some easy detection of buffer overruns. Disable these options when the highest performance, or most accurate profiling data, is required for your application. Support for these options is removed entirely in the Release configuration of the sound engine.

Tuning "Span Count"

If your Memory Manager integration relies on Wwise's integration of rpmalloc, it might be desirable to adjust AK::MemSettings::uVMSpanCount and AK::MemSettings::uDeviceSpanCount in order to reduce the amount of memory reserved by the system. There are three options available for these settings, which provide different trade-offs for CPU and Memory use: AkSpanCount_Small, AkSpanCount_Medium, and AkSpanCount_Huge.

AkSpanCount_Huge is the default value, which offers the best CPU performance by reducing the number of calls made to AkMemSettings::pfAllocVM, but also because in supported integrations, and on some platforms, memory mappings can be made using 2MiB pages, instead of 4KiB or 16KiB pages. Utilization of 2MiB pages can reduce the number of translation lookaside buffer (TLB) misses during sound engine execution, and help improve overall CPU performance.

AkSpanCount_Small adjusts the amount of memory requested at any given time to be as low as 64KiB. This can reduce the amount of memory reserved by Wwise, but can increase the amount of CPU usage due to an increase in calls to AkMemSettings::pfAllocVM. Depending on your implementation of the AkMemSettings::pfAllocVM callback, this might also prevent the usage of 2MiB pages for memory mappings.

AkSpanCount_Medium balances memory and CPU usage, by requesting memory blocks as low as 512KiB. This can reduce the number of calls to AkMemSettings::pfAllocVM compared to AkSpanCount_Small, but still might prevent the usage of 2MiB pages for memory mappings.

참고: If your implementation of AkMemSettings::pfAllocVM provides blocks of pre-mapped memory, and rarely invokes a system call for a new memory mapping, we strongly recommend that you use a setting of AkSpanCount_Small because the relative cost of calls to AkMemSettings::pfAllocVM should be greatly reduced, and your pre-mapped memory might already be using 2MiB pages.

이 페이지가 도움이 되었나요?

지원이 필요하신가요?

질문이 있으신가요? 문제를 겪고 계신가요? 더 많은 정보가 필요하신가요? 저희에게 문의해주시면 도와드리겠습니다!

지원 페이지를 방문해 주세요

작업하는 프로젝트에 대해 알려주세요. 언제든지 도와드릴 준비가 되어 있습니다.

프로젝트를 등록하세요. 아무런 조건이나 의무 사항 없이 빠른 시작을 도와드리겠습니다.

Wwise를 시작해 보세요