浏览代码

Tiny optimizations to avoid copies

Tomasz Zieliński 2 年之前
父节点
当前提交
99870be24c
共有 3 个文件被更改,包括 66 次插入40 次删除
  1. 7 9
      lib/rmg/RmgArea.cpp
  2. 54 28
      lib/rmg/RmgObject.cpp
  3. 5 3
      lib/rmg/RmgObject.h

+ 7 - 9
lib/rmg/RmgArea.cpp

@@ -238,6 +238,7 @@ bool Area::contains(const Area & area) const
 
 bool Area::overlap(const std::vector<int3> & tiles) const
 {
+	// Important: Make sure that tiles.size < area.size
 	for(const auto & t : tiles)
 	{
 		if(contains(t))
@@ -296,15 +297,14 @@ int3 Area::nearest(const Area & area) const
 Area Area::getSubarea(const std::function<bool(const int3 &)> & filter) const
 {
 	Area subset;
-	for(const auto & t : getTilesVector())
-		if(filter(t))
-			subset.add(t);
+	vstd::copy_if(getTilesVector(), vstd::set_inserter(subset.dTiles), filter);
 	return subset;
 }
 
 void Area::clear()
 {
 	dTiles.clear();
+	dTilesVectorCache.clear();
 	dTotalShiftCache = int3();
 	invalidate();
 }
@@ -329,11 +329,10 @@ void Area::erase(const int3 & tile)
 void Area::unite(const Area & area)
 {
 	invalidate();
-	for(const auto & t : area.getTilesVector())
-	{
-		dTiles.insert(t);
-	}
+	auto & vec = area.getTilesVector();
+	dTiles.insert(vec.begin(), vec.end());
 }
+
 void Area::intersect(const Area & area)
 {
 	invalidate();
@@ -359,7 +358,7 @@ void Area::translate(const int3 & shift)
 {
 	dBorderCache.clear();
 	dBorderOutsideCache.clear();
-	
+
 	if(dTilesVectorCache.empty())
 	{
 		getTiles();
@@ -373,7 +372,6 @@ void Area::translate(const int3 & shift)
 	{
 		t += shift;
 	}
-	//toAbsolute(dTiles, shift);
 }
 
 void Area::erase_if(std::function<bool(const int3&)> predicate)

+ 54 - 28
lib/rmg/RmgObject.cpp

@@ -199,20 +199,24 @@ Object::Object(const Object & object):
 	setPosition(object.getPosition());
 }
 
-std::list<Object::Instance*> Object::instances()
+std::list<Object::Instance*> & Object::instances()
 {
-	std::list<Object::Instance*> result;
-	for(auto & i : dInstances)
-		result.push_back(&i);
-	return result;
+	if (cachedInstanceList.empty())
+	{
+		for(auto & i : dInstances)
+			cachedInstanceList.push_back(&i);
+	}
+	return cachedInstanceList;
 }
 
-std::list<const Object::Instance*> Object::instances() const
+std::list<const Object::Instance*> & Object::instances() const
 {
-	std::list<const Object::Instance*> result;
-	for(const auto & i : dInstances)
-		result.push_back(&i);
-	return result;
+	if (cachedInstanceConstList.empty())
+	{
+		for(const auto & i : dInstances)
+			cachedInstanceConstList.push_back(&i);
+	}
+	return cachedInstanceConstList;
 }
 
 void Object::addInstance(Instance & object)
@@ -220,16 +224,22 @@ void Object::addInstance(Instance & object)
 	//assert(object.dParent == *this);
 	setGuardedIfMonster(object);
 	dInstances.push_back(object);
+	cachedInstanceList.push_back(&object);
+	cachedInstanceConstList.push_back(&object);
 
 	clearCachedArea();
+	visibleTopOffset.reset();
 }
 
 Object::Instance & Object::addInstance(CGObjectInstance & object)
 {
 	dInstances.emplace_back(*this, object);
 	setGuardedIfMonster(dInstances.back());
+	cachedInstanceList.push_back(&dInstances.back());
+	cachedInstanceConstList.push_back(&dInstances.back());
 
 	clearCachedArea();
+	visibleTopOffset.reset();
 	return dInstances.back();
 }
 
@@ -237,8 +247,11 @@ Object::Instance & Object::addInstance(CGObjectInstance & object, const int3 & p
 {
 	dInstances.emplace_back(*this, object, position);
 	setGuardedIfMonster(dInstances.back());
+	cachedInstanceList.push_back(&dInstances.back());
+	cachedInstanceConstList.push_back(&dInstances.back());
 
 	clearCachedArea();
+	visibleTopOffset.reset();
 	return dInstances.back();
 }
 
@@ -266,6 +279,7 @@ const rmg::Area & Object::getAccessibleArea(bool exceptLast) const
 	if(!exceptLast && !dAccessibleAreaFullCache.empty())
 		return dAccessibleAreaFullCache;
 	
+	// FIXME: This clears tiles for every consecutive object
 	for(auto i = dInstances.begin(); i != std::prev(dInstances.end()); ++i)
 		dAccessibleAreaCache.unite(i->getAccessibleArea());
 	
@@ -282,28 +296,27 @@ const rmg::Area & Object::getAccessibleArea(bool exceptLast) const
 
 const rmg::Area & Object::getBlockVisitableArea() const
 {
-	if(dInstances.empty())
-		return dBlockVisitableCache;
-
-	for(const auto & i : dInstances)
+	if(dBlockVisitableCache.empty())
 	{
-		// FIXME: Account for blockvis objects with multiple visitable tiles
-		if (i.isBlockedVisitable())
-			dBlockVisitableCache.add(i.getVisitablePosition());
+		for(const auto & i : dInstances)
+		{
+			// FIXME: Account for blockvis objects with multiple visitable tiles
+			if (i.isBlockedVisitable())
+				dBlockVisitableCache.add(i.getVisitablePosition());
+		}
 	}
-
 	return dBlockVisitableCache;
 }
 
 const rmg::Area & Object::getRemovableArea() const
 {
 	if(dInstances.empty())
-		return dRemovableAreaCache;
-
-	for(const auto & i : dInstances)
 	{
-		if (i.isRemovable())
-			dRemovableAreaCache.unite(i.getBlockedArea());
+		for(const auto & i : dInstances)
+		{
+			if (i.isRemovable())
+				dRemovableAreaCache.unite(i.getBlockedArea());
+		}
 	}
 
 	return dRemovableAreaCache;
@@ -341,6 +354,8 @@ void Object::setTemplate(const TerrainId & terrain, CRandomGenerator & rng)
 {
 	for(auto& i : dInstances)
 		i.setTemplate(terrain, rng);
+
+	visibleTopOffset.reset();
 }
 
 const Area & Object::getArea() const
@@ -358,15 +373,23 @@ const Area & Object::getArea() const
 
 const int3 Object::getVisibleTop() const
 {
-	int3 topTile(-1, 10000, -1); //Start at the bottom
-	for (const auto& i : dInstances)
+	if (visibleTopOffset)
+	{
+		return dPosition + visibleTopOffset.value();
+	}
+	else
 	{
-		if (i.getTopTile().y < topTile.y)
+		int3 topTile(-1, 10000, -1); //Start at the bottom
+		for (const auto& i : dInstances)
 		{
-			topTile = i.getTopTile();
+			if (i.getTopTile().y < topTile.y)
+			{
+				topTile = i.getTopTile();
+			}
 		}
+		visibleTopOffset = topTile - dPosition;
+		return topTile;
 	}
-	return topTile;
 }
 
 bool rmg::Object::isGuarded() const
@@ -444,6 +467,9 @@ void Object::clear()
 	for(auto & instance : dInstances)
 		instance.clear();
 	dInstances.clear();
+	cachedInstanceList.clear();
+	cachedInstanceConstList.clear();
+	visibleTopOffset.reset();
 
 	clearCachedArea();
 }

+ 5 - 3
lib/rmg/RmgObject.h

@@ -68,8 +68,8 @@ public:
 	Instance & addInstance(CGObjectInstance & object);
 	Instance & addInstance(CGObjectInstance & object, const int3 & position);
 	
-	std::list<Instance*> instances();
-	std::list<const Instance*> instances() const;
+	std::list<Instance*> & instances();
+	std::list<const Instance*> & instances() const;
 	
 	int3 getVisitablePosition() const;
 	const Area & getAccessibleArea(bool exceptLast = false) const;
@@ -98,7 +98,9 @@ private:
 	mutable Area dBlockVisitableCache;
 	mutable Area dRemovableAreaCache;
 	int3 dPosition;
-	ui32 dStrength;
+	mutable std::optional<int3> visibleTopOffset;
+	mutable std::list<Object::Instance*> cachedInstanceList;
+	mutable std::list<const Object::Instance*> cachedInstanceConstList;
 	bool guarded;
 };
 }