Jump to content



Photo

.NET Speach .UnloadGrammer SLOW!

.net speech

  • Please log in to reply
8 replies to this topic

#1 James Rose

James Rose

    Software Developer

  • Tech Issues Solved: 1
  • Joined: 20-January 04
  • Location: New York City

Posted 06 March 2013 - 22:26

Hello gang,

I am using the Speech.Recognition.GrammarBuilder to allow speech within an app. Everything works fine except when I unload grammer is takes up to 20 seconds.

For example; I have two sets of grammer. The first set contains navigation works (Up, Down, Select, etc) and the second set lists items (in this case names of files) When the user selects a new list the previous list of files is no longer needed so I need to remove them from the grammer.

If Not bMenuGrammer Is Nothing Then
		  Console.WriteLine("unload 1: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)
		  Me.bSpeechEngine.UnloadGrammar(bMenuGrammer)
		  Console.WriteLine("unload 2: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)
		  bMenuGrammer = Nothing
		  Console.WriteLine("unload 3: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)
End If

It should be worth mentioning that there are some details in the Output window (and Im sure this will make me look stupid...)
unload 1: 30.45.247
The thread '<No Name>' (0x155c) has exited with code 0 (0x0).
The thread '<No Name>' (0x2360) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x27c8) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x155c) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x2360) has exited with code 0 (0x0).
The thread '<No Name>' (0x2198) has exited with code 0 (0x0).
The thread 'Win32 Thread' (0x2198) has exited with code 0 (0x0).
unload 2: 30.46.357
unload 3: 30.46.357

The list can have as few as 1 item or maybe 100. Not a lot.
Between step 1 and 2 the wait can be 15 to 20 seconds

Any ideas?

Thanks


#2 ingramator

ingramator

    Hacker

  • Joined: 04-July 12
  • OS: Windows 7/8, OSX 10.8, Linux/UNIX/BSD
  • Phone: Lumia 920, iPhone 5, GS3

Posted 06 March 2013 - 22:46

I'm not 100% sure what you are actually trying to do! Are you running/targeting .NET 4.5 or <4? I must admit I've never actually used the grammarbuilder class but I trust you have read up on the MSDN page at http://msdn.microsof...marbuilder.aspx ?

#3 OP James Rose

James Rose

    Software Developer

  • Tech Issues Solved: 1
  • Joined: 20-January 04
  • Location: New York City

Posted 06 March 2013 - 22:55

I'm not 100% sure what you are actually trying to do! Are you running/targeting .NET 4.5 or <4? I must admit I've never actually used the grammarbuilder class but I trust you have read up on the MSDN page at http://msdn.microsof...marbuilder.aspx ?


I'm using Framework 4.0 and it works, that is not the issue. The issue is the time it takes to unload a set of grammar.

#4 ingramator

ingramator

    Hacker

  • Joined: 04-July 12
  • OS: Windows 7/8, OSX 10.8, Linux/UNIX/BSD
  • Phone: Lumia 920, iPhone 5, GS3

Posted 07 March 2013 - 08:18

I'm using Framework 4.0 and it works, that is not the issue. The issue is the time it takes to unload a set of grammar.


Yes I am aware of that but there was a major update to grammar in .NET 4 so I was curious to see if that could be causing problems. I really don't know why it would take so long, have fun.

#5 Eric

Eric

    Neowinian Senior

  • Tech Issues Solved: 13
  • Joined: 02-August 06
  • Location: Greenville, SC

Posted 07 March 2013 - 12:45

Are you calling the RequestRecognizerUpdate method to pause the engine first as this article mentions?
Also, if you're removing stuff that's no longer needed you could probably do it asynchronously.

Admittedly, it's been a while since I've meddled with the speech engine. :)

#6 OP James Rose

James Rose

    Software Developer

  • Tech Issues Solved: 1
  • Joined: 20-January 04
  • Location: New York City

Posted 07 March 2013 - 13:54

Are you calling the RequestRecognizerUpdate method to pause the engine first as this article mentions?
Also, if you're removing stuff that's no longer needed you could probably do it asynchronously.

Admittedly, it's been a while since I've meddled with the speech engine. :)


Thanks... I found something similar late last night and I am about to check it out.

It's interesting to me that it takes so long to remove data. I'm curious as to the reasons... but not SO curious to dig that deep.

Thank you again.

#7 OP James Rose

James Rose

    Software Developer

  • Tech Issues Solved: 1
  • Joined: 20-January 04
  • Location: New York City

Posted 21 March 2013 - 17:27

Well, I have been playing with several attempts to improve the speed of the UnloadGrammar. There is a function on the SpeechRecognitionEngine called RecognizerUpdateReached that you are to call. What follows is my current solution and it allows the UI to be accessible while the grammar is unloaded.

    Private Class UpdateGrammarRequest
	    Public RequestType As GrammarRequestType
	    Public Grammar As Grammar
	    Public Engine As SpeechRecognitionEngine
    End Class

    Private Enum GrammarRequestType
	    UnloadGrammar
	    LoadGrammar
    End Enum


'THIS CODE IS CALLED WHEN NEW WORDS HAVE BEEN ADDED.
'IT THEN CALLS THE OBJECT BediaSpeechEngine's function (below)
    Console.WriteLine("Before: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)

    Dim objUpdateGrammerRequest = New UpdateGrammarRequest()

    objUpdateGrammerRequest.RequestType = GrammarRequestType.UnloadGrammar
    objUpdateGrammerRequest.Grammar = BediaMenuGrammer
    objUpdateGrammerRequest.Engine = Me.BediaSpeechEngine

    Me.BediaSpeechEngine.RequestRecognizerUpdate(objUpdateGrammerRequest)
   
    Console.WriteLine("After: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)

Private Sub BediaSpeechEngine_RecognizerUpdateReached(sender As Object, e As RecognizerUpdateReachedEventArgs) Handles BediaSpeechEngine.RecognizerUpdateReached

	    Try
		    Dim request As UpdateGrammarRequest = e.UserToken

		    If Not request Is Nothing Then
			    Console.WriteLine("HERE 1: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)
			    Me.BediaSpeechEngine.UnloadGrammar(request.Grammar)
   
			    '-- Available Menus --
			    Dim MenuChoices As New System.Speech.Recognition.Choices()
			    Dim BediaGrammerBuilder As New Speech.Recognition.GrammarBuilder
			    Dim objMenuItem As MenuItem
			    Dim sValue As String
			    Dim sMenuText As String

			    For iMenus = 0 To (maryMenus.Count - 1)
				    objMenuItem = CType(maryMenus(iMenus), MenuItem)
				    MenuChoices.Add(New System.Speech.Recognition.SemanticResultValue(sMenuText, 4))
			    Next


			    BediaGrammerBuilder.Append(MenuChoices)
			    BediaMenuGrammer = Nothing
			    BediaMenuGrammer = New System.Speech.Recognition.Grammar(BediaGrammerBuilder)
			    Me.BediaSpeechEngine.LoadGrammarAsync(BediaMenuGrammer)

			    Console.WriteLine("HERE 2: " & Now.Minute.ToString & "." & Now.Second.ToString & "." & Now.Millisecond.ToString)

		    End If
		    

	    Catch ex As Exception
		    LogException(ex)
	    Finally

	    End Try

    End Sub

Here are the results:
Minute . Second . Millisecond
Before: 14.22.92
After: 14.22.92
HERE 1: 14.37.959
HERE 2: 14.37.984

FIFTEEN SECONDS?!!!

At least the UI works, but having to wait for 15 seconds until function is available to load the new values is harsh.

Any thoughts?

#8 Andre S.

Andre S.

    Asik

  • Tech Issues Solved: 12
  • Joined: 26-October 05

Posted 22 March 2013 - 02:20

Well let's interpret these results correctly first and foremost. The actual call to UnloadGrammer happens between the "HERE 1" and "HERE 2", and your numbers show that this takes about 25ms. Issuing the request to the speech recognition engine happens between the "before" and the "after", and those numbers show that no measurable time elapses then.

The 15 second difference appears to be the delay between the moment you issue the request and the moment the corresponding event handler is called by the speech recognition engine. This could be because it is busy with another long running operation. Have you issued a pause request before doing this as GreyWolf has pointed out?

#9 articuno1au

articuno1au

    Neowinian Senior

  • Tech Issues Solved: 2
  • Joined: 20-March 11
  • Location: Brisbane, Australia

Posted 22 March 2013 - 02:45

Would you mind throwing this into your code before you try and stop the Engine:
BediaSpeechEngine.RecognizeAsyncStop();
My theory is that you have something running in the background that's having to finish executing before you can unload it >.<