PlaySound API を繰り返し呼び出すと Audiodg.exe のメモリ使用量が増加する

こんにちは、マルチメディアサポートチームです。今回は、PlaySound API を繰り返し呼び出した場合に、Audiodg.exe のメモリ使用量が増加し続ける現象についてご説明します。

なお、本現象につきましては、音声の再生時のパフォーマンスを重視する必要があり、メモリ解放が低優先度となる仕様に基づく動作となります。

 

 

事象発生までの流れ

PlaySound API は、Windows にて特定の音データを再生するために利用する代表的なAPI です。

 

PlaySound function

https://msdn.microsoft.com/en-us/library/windows/desktop/dd743680(v=vs.85).aspx

 

このAPI は基本的に指定された音データのみを一度 再生します。そのため、継続的に音を再生する場合や複数の音源を再生する場合など、利用目的によっては、PlaySound API を繰り返して呼ぶ利用方法が考えられます。

 

ただ、繰り返して呼び出す利用方法にて、API の呼び出し間隔が(1 秒未満など) 短い場合は、時間の経過とともにOS 内のモジュールAudiodg.exe のメモリ使用量が徐々に増加する事象が発生します。この事象は、PlaySound が呼び出されている間は継続して発生します。

増加量の度合いは呼び出しの頻度や音データのサイズに影響されますが、目安として、50~100 ミリ秒程度の間隔でPlaySound API を繰り返し呼び出した場合、30~40 時間程度でAudiodg.exe のメモリ使用量が1 GB 単位に至ります。

 

事象の発生要因について

この事象は、Audiodg.exe が再生側のパフォーマンスを重視した処理を行っている結果として、メモリの解放処理が遅延しているために発生します。音声の再生には、周波数に応じたサンプリングデータ生成が必要です。もし処理が間に合わない場合には、正しい音が再生できないこととなるため、音声再生のパフォーマンスを重視する仕様となっております。

 

PlaySound API を呼び出した際は、OS 内の処理として、Windows オーディオ サービス (Audiosrv) がAudiodg.exe に対し呼び出し(RPC ※1) をかけます。Audiodg.exe は、その呼び出しに応じて、音の再生など必要な処理を行います。この際に、音データなど処理に必要なデータは(C++) オブジェクトとしてOS よりメモリ内に割り当てられています。

 

ただ、その再生処理が完了した後でも、Audiodg.exe は、その同じRPC 処理の中で割り当てられたメモリの開放を即座に行いません。これは、「音の再生」という優先度の高い処理を滞りなく実行するための、パフォーマンスの維持を考慮した結果の動作となっています。

その代わりAudiodg.exe は、後にメモリの開放を行うための印として、処理に利用したオブジェクトに対して、「利用済み」であることを表すフラグをセットします。

 

Audiodg.exe は、実際にメモリの開放を行う処理を、このフラグの有無をベースに、専用のスレッドを通して一定の間隔で行います。ただ、解放処理を実行するには、まずスレッドが開始できる状態である必要があります。

今回の事象が発生するような、短い間隔での音再生が繰り返されるAPI の利用方法では、Audiodg.exe にて専用スレッドの開始を行うためのリソースがない状況が続きます。その結果、解放処理は開始されず、メモリの割り当てのみが繰り返し行われ、メモリ使用量の増加が継続して発生します。

もし解放専用のスレッドが実行できる程度のリソースをAudiodg.exe が確保できる場合は、解放処理が始まり、メモリの開放が行われます。そのため、PlaySound API を実行しているプログラムが終了した場合、メモリ使用量の低下が見込まれます。

 

なお、この事象はあくまで後負荷の処理に起因した「メモリ使用量の増加」であるため、メモリ リークは発生しておりません。Audiodg.exe にて発生するメモリー リークについては、以下の既知の問題がありますが、この事象との関連性はございません。

 

Handle leak occurs in the Audiodg.exe process in Windows 7 or in Windows Server 2008 R2

https://support.microsoft.com/en-us/help/2670667/handle-leak-occurs-in-the-audiodg-exe-process-in-windows-7-or-in-windo

 

対処法について

上記の詳細の通り、この事象は、メモリの開放を行う動作が実行されることで解消します。そのため、対処法としては、以下の方法が考えられます。

 

·         PlaySound API を繰り返し呼び出す間隔を(数秒程度に) 広げ、解放処理を実行できる程度のリソースをAudiodg.exe で控えられるようにする

·         PlaySound API を一定期間呼ばない処理を加える

·         以下のコマンドなどで、Windows オーディオ サービス(Audiosrv) を一度 停止し、強制的に割り当てられたメモリを解放した後、サービスを再開させる

 

Net stop audiosrv

Net start audiosrv

 

 

補足

※ 1: Remote Procedure Call (RPC) の概要については、以下のドキュメントをご参照ください。

 

Remote Procedure Call https://msdn.microsoft.com/en-us/library/windows/desktop/aa378651(v=vs.85).aspx