Memory leak in .Net Speech.Synthesizer?
Asked Answered
O

3

8

I found a continuous leakage in my application. After examining using a memory profiler, I found the course is some object from Microsoft Speech.Synthesizer

So I build up a toy project to verify the hypothesis:

//Toy example to show memory leak in Speech.Synthesizer object

static void Main(string[] args)
{
    string text = "hello world. This is a long sentence";
    PromptBuilder pb = new PromptBuilder();
    pb.StartStyle(new PromptStyle(PromptRate.ExtraFast));
    pb.AppendText(text);
    pb.EndStyle();
    SpeechSynthesizer tts = new SpeechSynthesizer();

while (true)
{
    //SpeechSynthesizer tts = new SpeechSynthesizer();
    Console.WriteLine("Speaking..."); 
    tts.Speak(pb);

    //Print private working set sieze
    Console.WriteLine("Memory: {0} KB\n", (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString("0"));

    //tts.Dispose();    //also this doesn't work as well
    //tts = null;

    GC.Collect();   //a little help, but still leaks
}
}

And the result actually confirmed the memory leak is from Speech.Synthesizer

Speaking...

Memory: 42184 KB

Speaking... Memory: 42312 KB

Speaking... Memory: 42440 KB

Speaking... Memory: 42568 KB

Speaking... Memory: 42696 KB

Speaking... Memory: 42824 KB

Speaking... Memory: 43016 KB

Speaking... Memory: 43372 KB

I googled it and found many others have come across the same problem: 1: Constant Memory Leak in SpeechSynthesizer 2: http://connect.microsoft.com/VisualStudio/feedback/details/664196/system-speech-has-a-memory-leak

but sadly I didn't find any solution to it. Since its a problem already asked long time ago, so I want to ask if its been solved or not?

Many Thanks.

UPDATE:

Seems like while I switch to use SAPI COM dll rather than .Net Speech.Synthesizer package (although essentially they are the same thing), the memory stops leaking.

Why is the two invoke behavior (SAPI dll vs .net Speech package) have different memory behavior? As the latter seems is just a wrapper to the former SAPI dll.

    static void Test2()
{
    //SAPI COM component this time
    SpeechLib.SpVoiceClass tts = new SpeechLib.SpVoiceClass();
    tts.SetRate(5);
    string text = "hello world. This is a long sentence";
    //tts.Speak("helloWorld", SpeechLib.SpeechVoiceSpeakFlags.SVSFDefault);
while (true)
{

    Console.WriteLine("Speaking...");
    tts.Speak(text, SpeechLib.SpeechVoiceSpeakFlags.SVSFDefault);

    //Print private working set sieze
    Console.WriteLine("Memory: {0} KB\n", (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString("0"));

    GC.Collect();
}

}

Memory: 32044 KB

Speaking... Memory: 32044 KB

Speaking... Memory: 32044 KB

Speaking... Memory: 32044 KB

Speaking... Memory: 32044 KB

Speaking... Memory: 32044 KB

Speaking... Memory: 32044 KB

Speaking... Memory: 32044 KB

Ourself answered 22/5, 2012 at 17:42 Comment(0)
O
4

Final solution:

Google-ing relevant keywords telling me that it's actually a bug from Microsoft.

Seems like while I switch to use SAPI COM dll rather than .Net Speech.Synthesizer package (although essentially they are the same thing), the memory stops leaking.

Ourself answered 26/6, 2012 at 21:1 Comment(2)
Can you post any of those links? Is there an MS Connect issue for it?Montreal
@Montreal Yes, actually I read some users report in MS forum, the post is posted two years ago. That 's why I reach such conclusion. I will need to search again for the post I actually read last month...Ourself
F
3

I'm not sure all the details on the SpeechSynthesizer, but you could try using the disposable pattern here. Since SpeechSynthesizer implements IDisposable

Your code would look like the following:

while (true)
{
   using (SpeechSynthesizer tts = new SpeechSynthesizer())
   {
      Console.WriteLine("Speaking..."); 
      tts.Speak(pb);

      //Print private working set sieze
      Console.WriteLine("Memory: {0} KB\n",(Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString("0"));
   }
}

If you notice this is very similar to Microsoft's example Here

This looks to in fact be a memory leak, Have you tried using the Microsoft.Speech runtime? The syntax looks very similar and they have mentioned it shouldn't have the same issue.

Foolish answered 22/5, 2012 at 18:15 Comment(4)
Thank you:) but it still has the memory leaksOurself
It does look then based on Microsoft's own admission this leaks. See Edit above.Foolish
Why is the two invoke behavior (SAPI dll vs .net Speech package) have different memory behavior? As the latter seems is just a wrapper to the former SAPI dll.Ourself
I'm not sure, I'm going off of what a Microsoft representative said here: connect.microsoft.com/VisualStudio/feedback/details/664196/…Foolish
I
1

I know it is an old thread, but there is another solution for the problem. Use Microsoft.Speech.Synthesis.SpeechSynthesizer instead of System.Speech.Synthesis.SpeechSynthesizer.

Microsoft.Speech.Synthesis.SpeechSynthesizer is included in the Microsoft Speech Platform - Software Development Kit (SDK) (Version 11) - https://www.microsoft.com/en-us/download/details.aspx?id=27226

This version of the Synthesizer does not have the memory leak.

Itacolumite answered 8/5, 2018 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.