mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 12:18:36 +02:00
avoid duplicate parse of AvatarEntityData entries
This commit is contained in:
parent
c551a41e0a
commit
d2315c15a1
2 changed files with 57 additions and 8 deletions
|
@ -231,13 +231,40 @@ void Avatar::updateAvatarEntities() {
|
||||||
QScriptEngine scriptEngine;
|
QScriptEngine scriptEngine;
|
||||||
entityTree->withWriteLock([&] {
|
entityTree->withWriteLock([&] {
|
||||||
AvatarEntityMap avatarEntities = getAvatarEntityData();
|
AvatarEntityMap avatarEntities = getAvatarEntityData();
|
||||||
for (auto entityID : avatarEntities.keys()) {
|
AvatarEntityMap::const_iterator dataItr = avatarEntities.begin();
|
||||||
|
while (dataItr != avatarEntities.end()) {
|
||||||
|
// compute hash of data. TODO? cache this?
|
||||||
|
QByteArray data = dataItr.value();
|
||||||
|
uint32_t newHash = qHash(data);
|
||||||
|
|
||||||
|
// check to see if we recognize this hash and whether it was already successfully processed
|
||||||
|
QUuid entityID = dataItr.key();
|
||||||
|
MapOfAvatarEntityDataHashes::iterator stateItr = _avatarEntityDataHashes.find(entityID);
|
||||||
|
if (stateItr != _avatarEntityDataHashes.end()) {
|
||||||
|
if (stateItr.value().success) {
|
||||||
|
if (newHash == stateItr.value().hash) {
|
||||||
|
// data hasn't changed --> nothing to do
|
||||||
|
++dataItr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// NOTE: if the data was unsuccessful in producing an entity in the past
|
||||||
|
// we will try again just in case something changed (unlikely).
|
||||||
|
// Unfortunately constantly trying to build the entity for this data costs
|
||||||
|
// CPU cycles that we'd rather not spend.
|
||||||
|
// TODO? put a maximum number of tries on this?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// remember this hash for the future
|
||||||
|
stateItr = _avatarEntityDataHashes.insert(entityID, AvatarEntityDataHash(newHash));
|
||||||
|
}
|
||||||
|
++dataItr;
|
||||||
|
|
||||||
// see EntityEditPacketSender::queueEditEntityMessage for the other end of this. unpack properties
|
// see EntityEditPacketSender::queueEditEntityMessage for the other end of this. unpack properties
|
||||||
// and either add or update the entity.
|
// and either add or update the entity.
|
||||||
QByteArray jsonByteArray = avatarEntities.value(entityID);
|
QJsonDocument jsonProperties = QJsonDocument::fromBinaryData(data);
|
||||||
QJsonDocument jsonProperties = QJsonDocument::fromBinaryData(jsonByteArray);
|
|
||||||
if (!jsonProperties.isObject()) {
|
if (!jsonProperties.isObject()) {
|
||||||
qCDebug(interfaceapp) << "got bad avatarEntity json" << QString(jsonByteArray.toHex());
|
qCDebug(interfaceapp) << "got bad avatarEntity json" << QString(data.toHex());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,18 +292,22 @@ void Avatar::updateAvatarEntities() {
|
||||||
properties.setScript(noScript);
|
properties.setScript(noScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to build the entity
|
||||||
EntityItemPointer entity = entityTree->findEntityByEntityItemID(EntityItemID(entityID));
|
EntityItemPointer entity = entityTree->findEntityByEntityItemID(EntityItemID(entityID));
|
||||||
|
bool success = true;
|
||||||
// NOTE: we don't bother checking whether updateEntity or addEntity succeed here:
|
|
||||||
// if not we'll try again next time the data is changed. This is to close a performance DOS vector
|
|
||||||
// whereby invalid entity data is given to the AvatarMixer and constant retries kill performance.
|
|
||||||
if (entity) {
|
if (entity) {
|
||||||
if (entityTree->updateEntity(entityID, properties)) {
|
if (entityTree->updateEntity(entityID, properties)) {
|
||||||
entity->updateLastEditedFromRemote();
|
entity->updateLastEditedFromRemote();
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
entity = entityTree->addEntity(entityID, properties);
|
entity = entityTree->addEntity(entityID, properties);
|
||||||
|
if (!entity) {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
stateItr.value().success = success;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
||||||
|
@ -289,6 +320,14 @@ void Avatar::updateAvatarEntities() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// remove stale data hashes
|
||||||
|
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||||
|
MapOfAvatarEntityDataHashes::iterator stateItr = _avatarEntityDataHashes.find(entityID);
|
||||||
|
if (stateItr != _avatarEntityDataHashes.end()) {
|
||||||
|
_avatarEntityDataHashes.erase(stateItr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -269,6 +269,16 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class AvatarEntityDataHash {
|
||||||
|
public:
|
||||||
|
AvatarEntityDataHash(uint32_t h) : hash(h) {};
|
||||||
|
uint32_t hash { 0 };
|
||||||
|
bool success { false };
|
||||||
|
};
|
||||||
|
|
||||||
|
using MapOfAvatarEntityDataHashes = QMap<QUuid, AvatarEntityDataHash>;
|
||||||
|
MapOfAvatarEntityDataHashes _avatarEntityDataHashes;
|
||||||
|
|
||||||
uint64_t _lastRenderUpdateTime { 0 };
|
uint64_t _lastRenderUpdateTime { 0 };
|
||||||
int _leftPointerGeometryID { 0 };
|
int _leftPointerGeometryID { 0 };
|
||||||
int _rightPointerGeometryID { 0 };
|
int _rightPointerGeometryID { 0 };
|
||||||
|
|
Loading…
Reference in a new issue