So at Im trying to make a CMS system that utilizies the yahoo messenger SDK. THe idea is to have a self help robot be able to guide clients through certain problems. The conversation is run by two methods. One a script exists to respond back with a generic response. In each message recieved by the client the program will look for certan keywords and questions that will trigger a response out of an XML file. If it dosent find one it continues with the script. The program works but at a cost. Its a huge resource hog. In the program I have a class that handles all of the yahoo messenger functions like login, logout, recieve and send messages. I also have a class that I call conversations. This keeps rack of where the message came form, who it was going to and what position it was in within the scripted conversation. In my main program i initilize X amount of the client class based on how many different sites help accouts I am using. Each time it recieves a message it either creates a new conversation class because it dosent exist or it checks for the existing conversation and finds the sripted position. It obviously does all of the checks for keywords on the incoming message as well. This is my code for the shared event handler for recieving messages. My question is, is there anywayto make this more efficient.
Private Sub yahooclients_OnRec(ByVal sender As Object, ByVal buddy As String, ByVal message As String)
TotalRec = TotalRec + 1
Try
Dim c As YahooClient = CType(sender, YahooClient) 'Yahoo Client To Send Message From
showLog("From:" & buddy & " To:" & c.Account & " Message:" & message)
Dim msgSplit As String()
Dim retmsg As String
Dim smsg As String()
Dim n1 As XmlNode
Dim sran As New Random 'Random SPlit Message
Dim domran As New Random 'Random Domain ID
Dim Found1 As Boolean = False
Dim FoundIt As Integer = 0
Dim i As Integer = 0 'Keyword Counter
'Check Message For KeyWords By Splitting Each phrase by spaces
msgSplit = Split(message, " ")
For Each word In msgSplit
For Each value In KeywordInd
If value = word Then
n1 = m_nodelist.Item(i)
retmsg = n1.InnerText
GoTo ScrubMessage
End If
i = i + 1
Next
i = 0
Next
'Check For Conversations
If convos.Count = 0 Then
convos.Add(New Conversation(c.Account, buddy, 0))
retmsg = Script(0)
GoTo ScrubMessage
Else
For A As Integer = 0 To (convos.Count - 1)
If InStr(convos(A).TUser, c.Account) > 0 And InStr(convos(A).FUser, buddy) > 0 Then
Found1 = True
Exit For
End If
FoundIt = FoundIt + 1
Next
If Found1 = True Then
convos(FoundIt).SPosition = convos(FoundIt).SPosition + 1
'Send Next Position In Script
If convos(FoundIt).SPosition > (Script.Length - 1) Then
If convos(FoundIt).SPosition = Script.Length Then
TotalScript = TotalScript + 1
ToolStripStatusLabel10.Text = TotalScript
End If
Exit Sub
End If
retmsg = Script(convos(FoundIt).SPosition)
GoTo ScrubMessage
Else
convos.Add(New Conversation(c.Account, buddy, 0))
retmsg = Script(0)
GoTo ScrubMessage
End If
End If
ScrubMessage:
‘Strip out |
smsg = Split(retmsg, “|”)
'Pull A Random Response
If smsg.Length > 1 Then
retmsg = smsg(sran.Next(0, (smsg.Length) - 1))
Else
retmsg = smsg(0)
End If
'Check For Domain Indicator
If InStr(retmsg, "%") > 0 Then
TotalLink = TotalLink + 1
End If
retmsg = Replace(retmsg, "%s", Domains(domran.Next(0, (Domains.Length - 1))))
If CheckBox2.Checked = True Then 'send Message With Font and Color
retmsg = "<font face=" & """" & fname & """" & ">" & "[#FF80C0m" & retmsg & "</font>"
End If
showLog(("Sending Message: " & retmsg & " To: " & buddy & " From: " & c.Account))
c.SendMessage(buddy, retmsg)
TotalSent = TotalSent + 1
ToolStripStatusLabel4.Text = TotalSent 'Updates Sent Counter
ToolStripStatusLabel6.Text = TotalRec 'Updates Rec Counter
ToolStripStatusLabel8.Text = TotalLink 'Updates Links counter
Catch ex As Exception
showLog(ex.ToString)
End Try
End Sub
The program becomes really no resonsive with alot of accounts are asking questions etc.
There are few things that look like a good place to start.
1) Pull the code after ScrubMessage into it’s own function which takes the needed information as parameters. Then replace all the GoTos with calls. This probably will not improve performance, but makes the code easier for most people to understand (and convention says raw gotos are evil).
2) You are searching through a list for every word of every incoming message. Based on the usage, KeywordInd and m_nodelist are probably declared something like this:
Since the keyword list seems to be a key into the node list of values, I would suggest using a dictionary to simplify the code and potentially improve speed.
where the keys are the words from
KeywordIndand the values are theInnerTextfromm_nodelistwhich lets you say3) Try associating the conversation directly with the YahooClient object so you do not have to do the lookup every time to find the conversation. When you do that, you can also make sure that there is a
Conversationassociated with every client if desired.4) You are interacting directly with what look to be UI components in the handler. This requires that all handlers for all clients run on the UI thread. You would probably be better of raising some events from this handler and letting the form handle the events and post across to the UI thread as needed. The events would probably be
ScriptPositionAdvancedandResponseSentor something similar. The form/control could then handle these events and post to the UI thread according to the pattern used by your UI framework of choice, which you should be able to find with a quick search.