Bladeren bron

Improved hashing of element definition

Michael Ragazzon 6 jaren geleden
bovenliggende
commit
5cb9e1df4b
3 gewijzigde bestanden met toevoegingen van 23 en 10 verwijderingen
  1. 1 1
      Include/Rocket/Core/StyleSheet.h
  2. 2 1
      Samples/basic/benchmark/src/main.cpp
  3. 20 8
      Source/Core/StyleSheet.cpp

+ 1 - 1
Include/Rocket/Core/StyleSheet.h

@@ -104,7 +104,7 @@ private:
 	// Map of every node, even empty, un-styled, nodes.
 	NodeIndex complete_node_index;
 
-	typedef UnorderedMap< String, ElementDefinition* > ElementDefinitionCache;
+	typedef UnorderedMap< size_t, ElementDefinition* > ElementDefinitionCache;
 	// Index of element addresses to element definitions.
 	mutable ElementDefinitionCache address_cache;
 	// Index of node sets to element definitions.

+ 2 - 1
Samples/basic/benchmark/src/main.cpp

@@ -79,7 +79,8 @@ public:
 		  Memory pool for ElementMeta: 59.0  [ece191a]
 		  Include chobo flat containers: 65.0  [1696aa5]
 		  Move benchmark to its own sample (no code change, fps increase because of removal of animation elements): 68.0  [2433880]
-		  Keep the element's main sizing box local: 69.0 
+		  Keep the element's main sizing box local: 69.0  [cf928b2]
+		  Improved hashing of element definition: 70.0
 		
 		*/
 

+ 20 - 8
Source/Core/StyleSheet.cpp

@@ -39,6 +39,13 @@
 namespace Rocket {
 namespace Core {
 
+template <class T>
+static inline void hash_combine(std::size_t& seed, const T& v)
+{
+	std::hash<T> hasher;
+	seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
 // Sorts style nodes based on specificity.
 static bool StyleSheetNodeSort(const StyleSheetNode* lhs, const StyleSheetNode* rhs)
 {
@@ -129,7 +136,10 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 	}*/
 
 	// See if there are any styles defined for this element.
-	std::vector< const StyleSheetNode* > applicable_nodes;
+	// Using static to avoid allocations. Make sure we don't call this function recursively.
+	static std::vector< const StyleSheetNode* > applicable_nodes;
+	ROCKET_ASSERT(applicable_nodes.empty());
+	applicable_nodes.clear();
 
 	String tags[] = {element->GetTagName(), ""};
 	for (int i = 0; i < 2; i++)
@@ -190,17 +200,18 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 
 	// Check if this puppy has already been cached in the node index; it may be that it has already been created by an
 	// element with a different address but an identical output definition.
-	String node_ids;
-	for (size_t i = 0; i < applicable_nodes.size(); i++)
-		node_ids += CreateString(10, "%x ", applicable_nodes[i]);
-	for (PseudoClassList::iterator i = volatile_pseudo_classes.begin(); i != volatile_pseudo_classes.end(); ++i)
-		node_ids += CreateString(32, ":%s", (*i).c_str());
+	size_t seed = 0;
+	for (const auto* node : applicable_nodes)
+		hash_combine(seed, node);
+	for (const String& str : volatile_pseudo_classes)
+		hash_combine(seed, str);
 
-	cache_iterator = node_cache.find(node_ids);
+	cache_iterator = node_cache.find(seed);
 	if (cache_iterator != node_cache.end())
 	{
 		ElementDefinition* definition = (*cache_iterator).second;
 		definition->AddReference();
+		applicable_nodes.clear();
 		return definition;
 	}
 
@@ -214,9 +225,10 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 //	new_definition->AddReference();
 
 	// Add to the node cache.
-	node_cache[node_ids] = new_definition;
+	node_cache[seed] = new_definition;
 	new_definition->AddReference();
 
+	applicable_nodes.clear();
 	return new_definition;
 }