@WiZaRd: This thread was a great idea!
I was doing some profiling...
When I noted that in
CClientUDPSocket::SendTo() ipstr() took what I believed to be an excessive execution time for what it did. So, I looked at the code,(see the current code below)
ipstr() returns a CString object and for eMule that's CStringT. Now CString objects seem expensive to me anyway, but when I looked at
CAsyncSocket::CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags) I found the first thing it does to our newly created TChar CString is convert it to an ASCII string, it then takes that ASCII string and with
inet_addr(lpszAscii); turns it back to the uint32 value we started with in
dwIP!! Finally it makes a call to
SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags);
Original
CClientUDPSocket::SendTo()
[color="#000000"][color="#0000FF"]int[/color] CClientUDPSocket::SendTo([color="#0000FF"]char[/color]* lpBuf,[color="#0000FF"]int [/color]nBufLen,uint32 dwIP, uint16 nPort){
[color="#008000"]// NOTE: *** This function is invoked from a *different* thread![/color]
uint32 result = CAsyncSocket::SendTo(lpBuf,nBufLen,nPort,[b]ipstr(dwIP)[/b]);
[color="#0000FF"]if[/color] (result == (uint32)SOCKET_ERROR){
uint32 error = GetLastError();
if (error == WSAEWOULDBLOCK){
m_bWouldBlock = [color="#0000FF"]true[/color];
[color="#0000FF"]return[/color] -1;
}
[color="#0000FF"]if[/color] (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(error, 1));
}
[color="#0000FF"]return[/color] 0;[/color]
}
MFC
CAsyncSocket::CAsyncSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, int nFlags)
[size=1][color="#000000"]
[color="#008000"]// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright © Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.[/color]
[color="#0000FF"]int[/color] CAsyncSocket::SendTo([color="#0000FF"]const void[/color]* lpBuf, [color="#0000FF"]int[/color] nBufLen, UINT nHostPort, LPCTSTR lpszHostAddress, [color="#0000FF"]int[/color] nFlags)
{
USES_CONVERSION_EX;
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,[color="#0000FF"]sizeof[/color](sockAddr));
LPSTR lpszAscii;
[color="#0000FF"]if[/color] (lpszHostAddress != NULL)
{
lpszAscii = T2A_EX((LPTSTR)lpszHostAddress, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
[color="#0000FF"]if[/color] (lpszAscii == NULL)
{
[color="#008000"]// OUT OF MEMORY[/color]
WSASetLastError(ERROR_NOT_ENOUGH_MEMORY);
[color="#0000FF"]return[/color] FALSE;
}
}
[color="#0000FF"]else[/color]
{
lpszAscii = NULL;
}
sockAddr.sin_family = AF_INET;
[color="#0000FF"]if[/color] (lpszAscii == NULL)
sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
[color="#0000FF"]else[/color]
{
sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
[color="#0000FF"]if[/color] (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpszAscii);
[color="#0000FF"]if[/color] (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
[color="#0000FF"]else[/color]
{
WSASetLastError(WSAEINVAL);
[color="#0000FF"]return[/color] SOCKET_ERROR;
}
}
}
sockAddr.sin_port = htons((u_short)nHostPort);
[b][color="#0000FF"]return[/color] SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, [color="#0000FF"]sizeof[/color](sockAddr), nFlags);[/b]
}[/color][/size]
Below is my optimized version of
CClientUDPSocket::SendTo()
[color="#000000"][color="#0000FF"]int[/color] CClientUDPSocket::SendTo([color="#0000FF"]char[/color]* lpBuf,int nBufLen,uint32 dwIP, uint16 nPort){
[color="#008000"]// NOTE: *** This function is invoked from a *different* thread!
[b] //TK4 MOD 2.0c - Save converting dwIP from uint32 to a CStringT to ASCII then back to uint32[/color]
[color="#0000FF"]if[/color](dwIP == INADDR_BROADCAST)
{
WSASetLastError(WSAEINVAL);
[color="#0000FF"]if[/color] (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(WSAEINVAL, 1));
[color="#0000FF"]return[/color] 0;
}
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = dwIP;
sockAddr.sin_port = htons((u_short)nPort);
uint32 result = CAsyncSocket::SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, [color="#0000FF"]sizeof[/color](sockAddr), 0);[/b]
[color="#008000"]// uint32 result = CAsyncSocket::SendTo(lpBuf,nBufLen,nPort,ipstr(dwIP)); [/color]
[color="#0000FF"]if[/color] (result == (uint32)SOCKET_ERROR){
uint32 error = GetLastError();
[color="#0000FF"]if[/color] (error == WSAEWOULDBLOCK){
m_bWouldBlock = [color="#0000FF"]true[/color];
[color="#0000FF"]return[/color] -1;
}
[color="#0000FF"]if[/color] (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(error, 1));
}
[color="#0000FF"]return[/color] 0;
}[/color]
The same optimize can be applied to
CUDPSocket::SendTo()
The Optimized code is below
[color="#000000"][color="#0000FF"]int[/color] CUDPSocket::SendTo(BYTE* lpBuf, [color="#0000FF"]int[/color] nBufLen, uint32 dwIP, uint16 nPort)
{
[color="#008000"]// NOTE: *** This function is invoked from a *different* thread!
[b]//TK4 MOD 2.0c - Save converting dwIP from uint32 to a CStringT to ASCII then back to uint32[/color]
[color="#0000FF"]if[/color](dwIP == INADDR_BROADCAST)
{
WSASetLastError(WSAEINVAL);
[color="#0000FF"]if[/color] (thePrefs.GetVerbose())
DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(WSAEINVAL, 1));
[color="#0000FF"]return[/color] 0;
}
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0,[color="#0000FF"]sizeof[/color](sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = dwIP;
sockAddr.sin_port = htons((u_short)nPort);
[color="#0000FF"]int[/color] iResult = CAsyncSocket::SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), 0);[/b]
[color="#008000"] //int iResult = CAsyncSocket::SendTo(lpBuf, nBufLen, nPort, ipstr(dwIP));[/color]
[color="#0000FF"]if[/color] (iResult == SOCKET_ERROR) {
DWORD dwError = GetLastError();
[color="#0000FF"]if[/color] (dwError == WSAEWOULDBLOCK) {
m_bWouldBlock = [color="#0000FF"]true[/color];
[color="#0000FF"]return[/color] -1; [color="#008000"]// blocked[/color]
}
[color="#0000FF"]else[/color]{
[color="#0000FF"]if[/color] (thePrefs.GetVerbose())
theApp.QueueDebugLogLine([color="#0000FF"]false[/color], _T("Error: Server UDP socket: Failed to send packet to %s:%u - %s"), ipstr(dwIP), nPort, GetErrorMessage(dwError, 1));
[color="#0000FF"]return[/color] 0; [color="#008000"]// error[/color]
}
}
[color="#0000FF"]return[/color] 1; [color="#008000"]// success[/color]
}[/color]
Thanks for reading!
Fix Added! 07-01-2007
This post has been edited by BlueSonicBoy: 07 January 2007 - 07:09 PM