Fix high populated servers latency (#156)
* Fix high populated servers latency - Ported commit from TC repositories - Fixes server update diffs spikes, generating high latency when many players are online - Redefined UpdateMask class and removed redundant code from Object.cpp * Removed extra line of code.
This commit is contained in:
parent
ad12885aee
commit
83a8c500f1
@ -337,29 +337,15 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
|
||||
MANGOS_ASSERT(updateMask && updateMask->GetCount() == m_valuesCount);
|
||||
|
||||
*data << (uint8)updateMask->GetBlockCount();
|
||||
data->append(updateMask->GetMask(), updateMask->GetLength());
|
||||
|
||||
// checking the new bit extraction mechanic
|
||||
//#ifdef _DEBUG
|
||||
uint16 ix = 0;
|
||||
for (uint16 i = 0; i < m_valuesCount; i++)
|
||||
{
|
||||
if (updateMask->GetBit(i))
|
||||
{
|
||||
ix = updateMask->GetNextSetIndex(ix);
|
||||
if (i != ix)
|
||||
sLog.outError("ERROR BuildValuesUpdate: new index %u, should be %u for object type %u entry %u", ix, i, GetTypeId(), GetEntry());
|
||||
++ix;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
updateMask->AppendToPacket(data);
|
||||
|
||||
// 2 specialized loops for speed optimization in non-unit case
|
||||
if (isType(TYPEMASK_UNIT)) // unit (creature/player) case
|
||||
{
|
||||
uint16 index = 0;
|
||||
while ((index = updateMask->GetNextSetIndex(index)) < m_valuesCount)
|
||||
for (uint16 index = 0; index < m_valuesCount; ++index)
|
||||
{
|
||||
if(updateMask->GetBit(index))
|
||||
{
|
||||
if (index == UNIT_NPC_FLAGS)
|
||||
{
|
||||
uint32 appendValue = m_uint32Values[index];
|
||||
@ -406,7 +392,7 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
|
||||
else if (index == UNIT_DYNAMIC_FLAGS && GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
uint32 send_value = m_uint32Values[index];
|
||||
|
||||
|
||||
/* Initiate pointer to creature so we can check loot */
|
||||
if (Creature* my_creature = (Creature*)this)
|
||||
/* If the creature is NOT fully looted */
|
||||
@ -455,14 +441,15 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
|
||||
// send in current format (float as float, uint32 as uint32)
|
||||
*data << m_uint32Values[index];
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isType(TYPEMASK_GAMEOBJECT)) // gameobject case
|
||||
{
|
||||
uint16 index = 0;
|
||||
while ((index = updateMask->GetNextSetIndex(index)) < m_valuesCount)
|
||||
for (uint16 index = 0; index < m_valuesCount; ++index)
|
||||
{
|
||||
if (updateMask->GetBit(index))
|
||||
{
|
||||
// send in current format (float as float, uint32 as uint32)
|
||||
if (index == GAMEOBJECT_DYN_FLAGS)
|
||||
{
|
||||
@ -488,17 +475,18 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
|
||||
}
|
||||
else
|
||||
{ *data << m_uint32Values[index]; } // other cases
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // other objects case (no special index checks)
|
||||
{
|
||||
uint16 index = 0;
|
||||
while ((index = updateMask->GetNextSetIndex(index)) < m_valuesCount)
|
||||
for (uint16 index = 0; index < m_valuesCount; ++index)
|
||||
{
|
||||
// send in current format (float as float, uint32 as uint32)
|
||||
*data << m_uint32Values[index];
|
||||
++index;
|
||||
if (updateMask->GetBit(index))
|
||||
{
|
||||
// send in current format (float as float, uint32 as uint32)
|
||||
*data << m_uint32Values[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,132 +27,104 @@
|
||||
|
||||
#include "UpdateFields.h"
|
||||
#include "Errors.h"
|
||||
#ifdef WIN32
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
class UpdateMask
|
||||
{
|
||||
public:
|
||||
UpdateMask() : mCount(0), mBlocks(0), mUpdateMask(0) { }
|
||||
UpdateMask(const UpdateMask& mask) : mUpdateMask(0) { *this = mask; }
|
||||
/// Type representing how client reads update mask
|
||||
typedef uint32 ClientUpdateMaskType;
|
||||
|
||||
~UpdateMask()
|
||||
enum UpdateMaskCount
|
||||
{
|
||||
delete[] mUpdateMask;
|
||||
CLIENT_UPDATE_MASK_BITS = sizeof(ClientUpdateMaskType) * 8,
|
||||
};
|
||||
|
||||
UpdateMask() : _fieldCount(0), _blockCount(0), _bits(NULL) { }
|
||||
|
||||
UpdateMask(UpdateMask const& right)
|
||||
{
|
||||
SetCount(right.GetCount());
|
||||
memcpy(_bits, right._bits, sizeof(uint8) * _blockCount * 32);
|
||||
}
|
||||
|
||||
void SetBit(uint32 index)
|
||||
{
|
||||
((uint8*)mUpdateMask)[ index >> 3 ] |= 1 << (index & 0x7);
|
||||
}
|
||||
~UpdateMask() { delete[] _bits; }
|
||||
|
||||
void UnsetBit(uint32 index)
|
||||
{
|
||||
((uint8*)mUpdateMask)[ index >> 3 ] &= (0xff ^(1 << (index & 0x7)));
|
||||
}
|
||||
void SetBit(uint32 index) { _bits[index] = 1; }
|
||||
void UnsetBit(uint32 index) { _bits[index] = 0; }
|
||||
bool GetBit(uint32 index) const { return _bits[index] != 0; }
|
||||
|
||||
bool GetBit(uint32 index) const
|
||||
void AppendToPacket(ByteBuffer* data)
|
||||
{
|
||||
return (((uint8*)mUpdateMask)[ index >> 3 ] & (1 << (index & 0x7))) != 0;
|
||||
}
|
||||
|
||||
uint32 GetNextSetIndex(uint32 start) const
|
||||
{
|
||||
uint32 index = start;
|
||||
while (index <= mCount)
|
||||
for (uint32 i = 0; i < GetBlockCount(); ++i)
|
||||
{
|
||||
uint32 offset = ctz(mUpdateMask[index >> 5] >> (index & 0x1F));
|
||||
if (offset < (32 - (index & 0x1F)))
|
||||
return index + offset;
|
||||
else
|
||||
index += (32 - (index & 0x1F));
|
||||
ClientUpdateMaskType maskPart = 0;
|
||||
for (uint32 j = 0; j < CLIENT_UPDATE_MASK_BITS; ++j)
|
||||
if (_bits[CLIENT_UPDATE_MASK_BITS * i + j])
|
||||
maskPart |= 1 << j;
|
||||
|
||||
*data << maskPart;
|
||||
}
|
||||
return mCount;
|
||||
}
|
||||
|
||||
uint32 GetBlockCount() const { return mBlocks; }
|
||||
uint32 GetLength() const { return mBlocks << 2; }
|
||||
uint32 GetCount() const { return mCount; }
|
||||
uint8* GetMask() { return (uint8*)mUpdateMask; }
|
||||
uint32 GetBlockCount() const { return _blockCount; }
|
||||
uint32 GetCount() const { return _fieldCount; }
|
||||
|
||||
void SetCount(uint32 valuesCount)
|
||||
{
|
||||
delete[] mUpdateMask;
|
||||
delete[] _bits;
|
||||
|
||||
mCount = valuesCount;
|
||||
mBlocks = (valuesCount + 31) / 32;
|
||||
_fieldCount = valuesCount;
|
||||
_blockCount = (valuesCount + CLIENT_UPDATE_MASK_BITS - 1) / CLIENT_UPDATE_MASK_BITS;
|
||||
|
||||
mUpdateMask = new uint32[mBlocks];
|
||||
memset(mUpdateMask, 0, mBlocks << 2);
|
||||
_bits = new uint8[_blockCount * CLIENT_UPDATE_MASK_BITS];
|
||||
memset(_bits, 0, sizeof(uint8) * _blockCount * CLIENT_UPDATE_MASK_BITS);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if (mUpdateMask)
|
||||
{ memset(mUpdateMask, 0, mBlocks << 2); }
|
||||
if (_bits)
|
||||
memset(_bits, 0, sizeof(uint8) * _blockCount * CLIENT_UPDATE_MASK_BITS);
|
||||
}
|
||||
|
||||
UpdateMask& operator = (const UpdateMask& mask)
|
||||
UpdateMask& operator=(UpdateMask const& right)
|
||||
{
|
||||
SetCount(mask.mCount);
|
||||
memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2);
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
SetCount(right.GetCount());
|
||||
memcpy(_bits, right._bits, sizeof(uint8) * _blockCount * CLIENT_UPDATE_MASK_BITS);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UpdateMask& operator&=(UpdateMask const& right)
|
||||
{
|
||||
MANGOS_ASSERT(right.GetCount() <= GetCount());
|
||||
for (uint32 i = 0; i < _fieldCount; ++i)
|
||||
_bits[i] &= right._bits[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator &= (const UpdateMask& mask)
|
||||
UpdateMask& operator|=(UpdateMask const& right)
|
||||
{
|
||||
MANGOS_ASSERT(mask.mCount <= mCount);
|
||||
for (uint32 i = 0; i < mBlocks; ++i)
|
||||
{ mUpdateMask[i] &= mask.mUpdateMask[i]; }
|
||||
MANGOS_ASSERT(right.GetCount() <= GetCount());
|
||||
for (uint32 i = 0; i < _fieldCount; ++i)
|
||||
_bits[i] |= right._bits[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator |= (const UpdateMask& mask)
|
||||
UpdateMask operator|(UpdateMask const& right)
|
||||
{
|
||||
MANGOS_ASSERT(mask.mCount <= mCount);
|
||||
for (uint32 i = 0; i < mBlocks; ++i)
|
||||
{ mUpdateMask[i] |= mask.mUpdateMask[i]; }
|
||||
}
|
||||
|
||||
UpdateMask operator & (const UpdateMask& mask) const
|
||||
{
|
||||
MANGOS_ASSERT(mask.mCount <= mCount);
|
||||
|
||||
UpdateMask newmask;
|
||||
newmask = *this;
|
||||
newmask &= mask;
|
||||
|
||||
return newmask;
|
||||
}
|
||||
|
||||
UpdateMask operator | (const UpdateMask& mask) const
|
||||
{
|
||||
MANGOS_ASSERT(mask.mCount <= mCount);
|
||||
|
||||
UpdateMask newmask;
|
||||
newmask = *this;
|
||||
newmask |= mask;
|
||||
|
||||
return newmask;
|
||||
UpdateMask ret(*this);
|
||||
ret |= right;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 mCount;
|
||||
uint32 mBlocks;
|
||||
uint32* mUpdateMask;
|
||||
|
||||
#ifdef WIN32
|
||||
static uint32 __inline __builtin_ctz(uint32 x)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
_BitScanForward(&r, x);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
static inline uint32 ctz(const uint32 x)
|
||||
{
|
||||
return x ? __builtin_ctz(x) : 32;
|
||||
}
|
||||
uint32 _fieldCount;
|
||||
uint32 _blockCount;
|
||||
uint8* _bits;
|
||||
};
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user