SMFac::Execute和SMFac::ExecuteForCheckpoint分别是状态机执行和checkpoint执行的热路径,应该消除不必要的string拷贝。
原代码路径:
src/sm-base/sm_base.cpp
// ...
bool SMFac :: Execute(const int iGroupIdx, const uint64_t llInstanceID, const std::string & sPaxosValue, SMCtx * poSMCtx)
{
if (sPaxosValue.size() < sizeof(int))
{
PLG1Err("Value wrong, instanceid %lu size %zu", llInstanceID, sPaxosValue.size());
//need do nothing, just skip
return true;
}
int iSMID = 0;
memcpy(&iSMID, sPaxosValue.data(), sizeof(int));
if (iSMID == 0)
{
PLG1Imp("Value no need to do sm, just skip, instanceid %lu", llInstanceID);
return true;
}
// 先把body拷贝到string临时对象,再从string临时对象拷贝到sBodyValue。
// 对于BatchExecute只用到从sPaxosValue.data() + sizeof(int)开始长度为sPaxosValue.size() - sizeof(int)的内容反序列化,没必要创建sBodyValue。
// 对于DoExecute需要用到sBodyValue,但创建sBodyValue过程中没必要引入string临时对象。
std::string sBodyValue = string(sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int));
if (iSMID == BATCH_PROPOSE_SMID)
{
BatchSMCtx * poBatchSMCtx = nullptr;
if (poSMCtx != nullptr && poSMCtx->m_pCtx != nullptr)
{
poBatchSMCtx = (BatchSMCtx *)poSMCtx->m_pCtx;
}
return BatchExecute(iGroupIdx, llInstanceID, sBodyValue, poBatchSMCtx);
}
else
{
return DoExecute(iGroupIdx, llInstanceID, sBodyValue, iSMID, poSMCtx);
}
}
bool SMFac :: BatchExecute(const int iGroupIdx, const uint64_t llInstanceID, const std::string & sBodyValue, BatchSMCtx * poBatchSMCtx)
{
BatchPaxosValues oBatchValues;
bool bSucc = oBatchValues.ParseFromArray(sBodyValue.data(), sBodyValue.size());
if (!bSucc)
{
PLG1Err("ParseFromArray fail, valuesize %zu", sBodyValue.size());
return false;
}
if (poBatchSMCtx != nullptr)
{
if ((int)poBatchSMCtx->m_vecSMCtxList.size() != oBatchValues.values_size())
{
PLG1Err("values size %d not equal to smctx size %zu",
oBatchValues.values_size(), poBatchSMCtx->m_vecSMCtxList.size());
return false;
}
}
for (int i = 0; i < oBatchValues.values_size(); i++)
{
const PaxosValue & oValue = oBatchValues.values(i);
SMCtx * poSMCtx = poBatchSMCtx != nullptr ? poBatchSMCtx->m_vecSMCtxList[i] : nullptr;
bool bExecuteSucc = DoExecute(iGroupIdx, llInstanceID, oValue.value(), oValue.smid(), poSMCtx);
if (!bExecuteSucc)
{
return false;
}
}
return true;
}
// ...
bool SMFac :: ExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID, const std::string & sPaxosValue)
{
if (sPaxosValue.size() < sizeof(int))
{
PLG1Err("Value wrong, instanceid %lu size %zu", llInstanceID, sPaxosValue.size());
//need do nothing, just skip
return true;
}
int iSMID = 0;
memcpy(&iSMID, sPaxosValue.data(), sizeof(int));
if (iSMID == 0)
{
PLG1Imp("Value no need to do sm, just skip, instanceid %lu", llInstanceID);
return true;
}
// 先把body拷贝到string临时对象,再从string临时对象拷贝到sBodyValue。
// 对于BatchExecuteForCheckpoint只用到从sPaxosValue.data() + sizeof(int)开始长度为sPaxosValue.size() - sizeof(int)的内容反序列化,没必要创建sBodyValue。
// **对于DoExecuteForCheckpoint需要用到sBodyValue,但创建sBodyValue过程中没必要引入string临时对象。**
std::string sBodyValue = string(sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int));
if (iSMID == BATCH_PROPOSE_SMID)
{
return BatchExecuteForCheckpoint(iGroupIdx, llInstanceID, sBodyValue);
}
else
{
return DoExecuteForCheckpoint(iGroupIdx, llInstanceID, sBodyValue, iSMID);
}
}
bool SMFac :: BatchExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID,
const std::string & sBodyValue)
{
BatchPaxosValues oBatchValues;
bool bSucc = oBatchValues.ParseFromArray(sBodyValue.data(), sBodyValue.size());
if (!bSucc)
{
PLG1Err("ParseFromArray fail, valuesize %zu", sBodyValue.size());
return false;
}
for (int i = 0; i < oBatchValues.values_size(); i++)
{
const PaxosValue & oValue = oBatchValues.values(i);
bool bExecuteSucc = DoExecuteForCheckpoint(iGroupIdx, llInstanceID, oValue.value(), oValue.smid());
if (!bExecuteSucc)
{
return false;
}
}
return true;
}
修改后代码路径:
src/sm-base/sm_base.h
// ...
/*
bool BatchExecute(const int iGroupIdx, const uint64_t llInstanceID,
const std::string & sBodyValue, BatchSMCtx * poBatchSMCtx);
*/
bool BatchExecute(const int iGroupIdx, const uint64_t llInstanceID,
const char* body, size_t body_len, BatchSMCtx * poBatchSMCtx);
/*
bool BatchExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID,
const std::string & sBodyValue);
*/
bool BatchExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID,
const char* body, size_t body_len);
// ...
src/sm-base/sm_base.cpp
// ...
bool SMFac :: Execute(const int iGroupIdx, const uint64_t llInstanceID, const std::string & sPaxosValue, SMCtx * poSMCtx)
{
if (sPaxosValue.size() < sizeof(int))
{
PLG1Err("Value wrong, instanceid %lu size %zu", llInstanceID, sPaxosValue.size());
//need do nothing, just skip
return true;
}
int iSMID = 0;
memcpy(&iSMID, sPaxosValue.data(), sizeof(int));
if (iSMID == 0)
{
PLG1Imp("Value no need to do sm, just skip, instanceid %lu", llInstanceID);
return true;
}
// std::string sBodyValue = string(sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int));
if (iSMID == BATCH_PROPOSE_SMID)
{
BatchSMCtx * poBatchSMCtx = nullptr;
if (poSMCtx != nullptr && poSMCtx->m_pCtx != nullptr)
{
poBatchSMCtx = (BatchSMCtx *)poSMCtx->m_pCtx;
}
// return BatchExecute(iGroupIdx, llInstanceID, sBodyValue, poBatchSMCtx);
// 没有创建sBodyValue
return BatchExecute(iGroupIdx, llInstanceID, sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int), poBatchSMCtx);
}
else
{
// 创建sBodyValue,没有临时string对象
std::string sBodyValue(sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int);
return DoExecute(iGroupIdx, llInstanceID, sBodyValue, iSMID, poSMCtx);
}
}
// bool SMFac :: BatchExecute(const int iGroupIdx, const uint64_t llInstanceID, const std::string & sBodyValue, BatchSMCtx * poBatchSMCtx)
bool SMFac :: BatchExecute(const int iGroupIdx, const uint64_t llInstanceID, const char* body, size_t body_len, BatchSMCtx * poBatchSMCtx)
{
BatchPaxosValues oBatchValues;
// bool bSucc = oBatchValues.ParseFromArray(sBodyValue.data(), sBodyValue.size());
bool bSucc = oBatchValues.ParseFromArray(body, body_len);
if (!bSucc)
{
// PLG1Err("ParseFromArray fail, valuesize %zu", sBodyValue.size());
PLG1Err("ParseFromArray fail, valuesize %zu", body_len);
return false;
}
if (poBatchSMCtx != nullptr)
{
if ((int)poBatchSMCtx->m_vecSMCtxList.size() != oBatchValues.values_size())
{
PLG1Err("values size %d not equal to smctx size %zu",
oBatchValues.values_size(), poBatchSMCtx->m_vecSMCtxList.size());
return false;
}
}
for (int i = 0; i < oBatchValues.values_size(); i++)
{
const PaxosValue & oValue = oBatchValues.values(i);
SMCtx * poSMCtx = poBatchSMCtx != nullptr ? poBatchSMCtx->m_vecSMCtxList[i] : nullptr;
bool bExecuteSucc = DoExecute(iGroupIdx, llInstanceID, oValue.value(), oValue.smid(), poSMCtx);
if (!bExecuteSucc)
{
return false;
}
}
return true;
}
// ...
bool SMFac :: ExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID, const std::string & sPaxosValue)
{
if (sPaxosValue.size() < sizeof(int))
{
PLG1Err("Value wrong, instanceid %lu size %zu", llInstanceID, sPaxosValue.size());
//need do nothing, just skip
return true;
}
int iSMID = 0;
memcpy(&iSMID, sPaxosValue.data(), sizeof(int));
if (iSMID == 0)
{
PLG1Imp("Value no need to do sm, just skip, instanceid %lu", llInstanceID);
return true;
}
// std::string sBodyValue = string(sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int));
if (iSMID == BATCH_PROPOSE_SMID)
{
// return BatchExecuteForCheckpoint(iGroupIdx, llInstanceID, sBodyValue);
// 没有创建sBodyValue
return BatchExecuteForCheckpoint(iGroupIdx, llInstanceID, sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int));
}
else
{
// 创建sBodyValue,没有临时string对象
std::string sBodyValue(sPaxosValue.data() + sizeof(int), sPaxosValue.size() - sizeof(int);
return DoExecuteForCheckpoint(iGroupIdx, llInstanceID, sBodyValue, iSMID);
}
}
/*
bool SMFac :: BatchExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID,
const std::string & sBodyValue)
*/
bool SMFac :: BatchExecuteForCheckpoint(const int iGroupIdx, const uint64_t llInstanceID,
const char* body, size_t body_len)
{
BatchPaxosValues oBatchValues;
// bool bSucc = oBatchValues.ParseFromArray(sBodyValue.data(), sBodyValue.size());
bool bSucc = oBatchValues.ParseFromArray(body, body_len);
if (!bSucc)
{
// PLG1Err("ParseFromArray fail, valuesize %zu", sBodyValue.size());
PLG1Err("ParseFromArray fail, valuesize %zu", body_len);
return false;
}
for (int i = 0; i < oBatchValues.values_size(); i++)
{
const PaxosValue & oValue = oBatchValues.values(i);
bool bExecuteSucc = DoExecuteForCheckpoint(iGroupIdx, llInstanceID, oValue.value(), oValue.smid());
if (!bExecuteSucc)
{
return false;
}
}
return true;
}
SMFac::Execute和SMFac::ExecuteForCheckpoint分别是状态机执行和checkpoint执行的热路径,应该消除不必要的string拷贝。
原代码路径:
src/sm-base/sm_base.cpp
修改后代码路径:
src/sm-base/sm_base.h
src/sm-base/sm_base.cpp