MessageEvent::DoOnWrite是发消息的热路径,应该消除不必要的buffer拷贝。
通过本类新增iovec 结构体数组成员变量暂存niBuffLen和poMessage,新增成员变量暂存已发送的字节个数,使用 writev 系统调用,再对逻辑做适当的修改就能消除buffer拷贝 。
原代码路径:
src/communicate/tcp/message_event.cpp
int MessageEvent :: DoOnWrite()
{
if (m_iLeftWriteLen > 0)
{
return WriteLeft();
}
m_oMutex.lock();
if (m_oInQueue.empty())
{
m_oMutex.unlock();
return 0;
}
QueueData tData = m_oInQueue.front();
m_oInQueue.pop();
m_iQueueMemSize -= tData.psValue->size();
m_oMutex.unlock();
std::string * poMessage = tData.psValue;
uint64_t llNowTime = Time::GetSteadyClockMS();
int iDelayMs = llNowTime > tData.llEnqueueAbsTime ? (int)(llNowTime - tData.llEnqueueAbsTime) : 0;
BP->GetNetworkBP()->TcpOutQueue(iDelayMs);
if (iDelayMs > TCP_OUTQUEUE_DROP_TIMEMS)
{
//PLErr("drop request because enqueue timeout, nowtime %lu unqueuetime %lu",
//llNowTime, tData.llEnqueueAbsTime);
delete poMessage;
return 0;
}
int iBuffLen = poMessage->size();
int niBuffLen = htonl(iBuffLen + 4);
int iLen = iBuffLen + 4;
// 没有必要拷贝niBuffLen和poMessage到buffer
// 通过本类的成员变量暂存niBuffLen和poMessage,以及记录发送的字节个数,再对逻辑做适当的修改就能消除buffer拷贝
m_oWriteCacheBuffer.Ready(iLen);
memcpy(m_oWriteCacheBuffer.GetPtr(), &niBuffLen, 4);
memcpy(m_oWriteCacheBuffer.GetPtr() + 4, poMessage->c_str(), iBuffLen);
m_iLeftWriteLen = iLen;
m_iLastWritePos = 0;
delete poMessage;
//PLImp("write len %d ip %s port %d", iLen, m_oAddr.getHost().c_str(), m_oAddr.getPort());
int iWriteLen = m_oSocket.send(m_oWriteCacheBuffer.GetPtr(), iLen);
if (iWriteLen < 0)
{
PLErr("fail, write len %d ip %s port %d",
iWriteLen, m_oAddr.getHost().c_str(), m_oAddr.getPort());
return -1;
}
if (iWriteLen == 0)
{
//need wait next write
AddEvent(EPOLLOUT);
return 1;
}
//PLImp("real write len %d", iWriteLen);
if (iWriteLen == iLen)
{
m_iLeftWriteLen = 0;
m_iLastWritePos = 0;
//write done
}
else if (iWriteLen < iLen)
{
m_iLastWritePos = iWriteLen;
m_iLeftWriteLen = iLen - iWriteLen;
PLImp("write buflen %d smaller than expectlen %d", iWriteLen, iLen);
}
else
{
PLErr("write buflen %d large than expectlen %d", iWriteLen, iLen);
}
return 0;
}
MessageEvent::DoOnWrite是发消息的热路径,应该消除不必要的buffer拷贝。
通过本类新增iovec 结构体数组成员变量暂存niBuffLen和poMessage,新增成员变量暂存已发送的字节个数,使用 writev 系统调用,再对逻辑做适当的修改就能消除buffer拷贝 。
原代码路径:
src/communicate/tcp/message_event.cpp