T
Tom
I have been running the CLR Profiler to find out where our memory leak
issues are. After some analysis, I found the #1 memory hog was in our
TCP listener thread. It took me a second to figure out what was so
wrong with it. Here is a look, can you spot it:
While m_bRunning
Try
' See if there is pending data in the socket buffer
If server.Pending Then
' If there is pending data, keep looping until
there is no more pending data
While server.Pending
' Perform a blocking call to accept requests
Dim client As System.Net.Sockets.TcpClient =
server.AcceptTcpClient()
data = Nothing
' Get a stream object for reading and writing
Dim stream As System.Net.Sockets.NetworkStream
= client.GetStream()
'Check to see if this Network Stream is
readable
If stream.CanRead Then
Dim bLoop As Boolean = True
'Wait for data to be available
While bLoop
'Check to see if data is available
If (stream.DataAvailable = True) Then
bLoop = False
If (System.DateTime.Now >
dtgLastResponseTimer) Then bLoop = False
End While
Dim txtXML As String = ""
Dim intTotalBytes As Int64 = 0
'If timeout was not reached, read from
stream
Do
Dim bytes(client.ReceiveBufferSize) As
Byte
' Loop to receive all the data sent by
the client.
Dim i As Int32 = 0
i = stream.Read(bytes, 0,
bytes.Length)
intTotalBytes = intTotalBytes + i
'Call WriteToDebug("Read " & i & "
bytes")
'Read contents of Request file
txtXML = txtXML &
System.Text.Encoding.ASCII.GetString(bytes, 0, i)
Loop While stream.DataAvailable
'Call WriteToDebug("Received " &
intTotalBytes & " total bytes")
'Ensure we have the entire message
Call ProcessRequest(txtXML, stream)
Else
'No data to read
Call WriteToDebug("Cannot read from
Network stream ")
End If
' Shutdown and end connection
client.Close()
stream.Close()
'Call WriteToDebug("Connection to client
closed: " + Format(System.DateTime.Now, "hh:mm:ss MMM-dd-yyyy"))
End While
Else
' There are no pending events, so pause
'Application.DoEvents()
System.Threading.Thread.Sleep(250)
End If
Catch
End Try
'ErrorHandler:
' If (Err.Number <> 0) Then
' Call WriteToDebug("SNMP Web Service
Startup Error:" & Err.Description)
' Err.Clear()
' End If
End While
Well, I know there were a LOT of byte being created, and I then saw:
Dim bytes(client.ReceiveBufferSize) As Byte
I did not know this but the buffer value is fixed at 32768! So for
the 50+ messages that came in, 1.7Meg of memory was being allocated.
The GC was running constantly. Well, looking at other examples, I
noticed that others have done the same thing. So does anyone know a
more efficient method to read data off of the socket. I would
obviously only use a single byte[] for reuse, but is there something
simpler?
Tom
P.S. - I did not write this code
issues are. After some analysis, I found the #1 memory hog was in our
TCP listener thread. It took me a second to figure out what was so
wrong with it. Here is a look, can you spot it:
While m_bRunning
Try
' See if there is pending data in the socket buffer
If server.Pending Then
' If there is pending data, keep looping until
there is no more pending data
While server.Pending
' Perform a blocking call to accept requests
Dim client As System.Net.Sockets.TcpClient =
server.AcceptTcpClient()
data = Nothing
' Get a stream object for reading and writing
Dim stream As System.Net.Sockets.NetworkStream
= client.GetStream()
'Check to see if this Network Stream is
readable
If stream.CanRead Then
Dim bLoop As Boolean = True
'Wait for data to be available
While bLoop
'Check to see if data is available
If (stream.DataAvailable = True) Then
bLoop = False
If (System.DateTime.Now >
dtgLastResponseTimer) Then bLoop = False
End While
Dim txtXML As String = ""
Dim intTotalBytes As Int64 = 0
'If timeout was not reached, read from
stream
Do
Dim bytes(client.ReceiveBufferSize) As
Byte
' Loop to receive all the data sent by
the client.
Dim i As Int32 = 0
i = stream.Read(bytes, 0,
bytes.Length)
intTotalBytes = intTotalBytes + i
'Call WriteToDebug("Read " & i & "
bytes")
'Read contents of Request file
txtXML = txtXML &
System.Text.Encoding.ASCII.GetString(bytes, 0, i)
Loop While stream.DataAvailable
'Call WriteToDebug("Received " &
intTotalBytes & " total bytes")
'Ensure we have the entire message
Call ProcessRequest(txtXML, stream)
Else
'No data to read
Call WriteToDebug("Cannot read from
Network stream ")
End If
' Shutdown and end connection
client.Close()
stream.Close()
'Call WriteToDebug("Connection to client
closed: " + Format(System.DateTime.Now, "hh:mm:ss MMM-dd-yyyy"))
End While
Else
' There are no pending events, so pause
'Application.DoEvents()
System.Threading.Thread.Sleep(250)
End If
Catch
End Try
'ErrorHandler:
' If (Err.Number <> 0) Then
' Call WriteToDebug("SNMP Web Service
Startup Error:" & Err.Description)
' Err.Clear()
' End If
End While
Well, I know there were a LOT of byte being created, and I then saw:
Dim bytes(client.ReceiveBufferSize) As Byte
I did not know this but the buffer value is fixed at 32768! So for
the 50+ messages that came in, 1.7Meg of memory was being allocated.
The GC was running constantly. Well, looking at other examples, I
noticed that others have done the same thing. So does anyone know a
more efficient method to read data off of the socket. I would
obviously only use a single byte[] for reuse, but is there something
simpler?
Tom
P.S. - I did not write this code