From d780d8a158700c843a4ee924a599d050e91ca275 Mon Sep 17 00:00:00 2001 From: Nick Holland Date: Tue, 14 Oct 2014 08:17:35 +0100 Subject: [PATCH] Optimized shader hash to not allocate memory or perform multiple passes of string data Applications like dali-demo end up hashing around 1MB of shader source on startup due to multiple calls to ShaderFactory::Load ( 340 calls for dali-demo). The previous code would: - Allocate a new string to hold both vertex/ fragment source code - Copy vertex / fragment source code in to the new string - Pass through the string removing white spaces - Pass through the string removing tabs - Pass through the string removing new line characters - Pass through the string to perform Hash calculation So if a total of 1MB is passed to the hasher it would end read/ writing around 5MB of data. Hence OProfile flagged it up as being a bottleneck for some apps on startup. New version does no memory allocation and does a single pass of the data. Todo: Need to look at a better way of comparing shaders Change-Id: I39c8b351c65c6e91f2c4b32e321f861d634ccca4 --- dali/internal/common/dali-hash.cpp | 32 +++++++++++++++++++++----- dali/internal/common/dali-hash.h | 23 ++++++++++++++---- dali/internal/event/effects/shader-factory.cpp | 15 +----------- dali/internal/event/effects/shader-factory.h | 8 ------- dali/internal/event/images/image-factory.cpp | 3 +-- dali/internal/event/text/font-factory.cpp | 8 ++----- 6 files changed, 49 insertions(+), 40 deletions(-) diff --git a/dali/internal/common/dali-hash.cpp b/dali/internal/common/dali-hash.cpp index e77839d..f154b14 100644 --- a/dali/internal/common/dali-hash.cpp +++ b/dali/internal/common/dali-hash.cpp @@ -22,21 +22,41 @@ namespace Dali { +namespace //un-named namespace +{ /* * djb2 (http://www.cse.yorku.ca/~oz/hash.html) */ -unsigned long StringHash::operator()(const std::string& toHash) -{ - unsigned long hash = 5381; +const unsigned long INITIAL_HASH_VALUE = 5381; - const char *str = toHash.c_str(); - - while( int c = *str++ ) +inline void HashShader( const char* string, unsigned long& hash ) +{ + while( int c = *string++ ) { hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ } +} +} // un-named namespace + +unsigned long CalculateHash(const std::string& toHash) +{ + unsigned long hash = INITIAL_HASH_VALUE; + + HashShader( toHash.c_str(), hash ); return hash; } +unsigned long CalculateHash(const std::string& string1, const std::string& string2) +{ + unsigned long hash = INITIAL_HASH_VALUE; + + HashShader( string1.c_str(), hash); + HashShader( string2.c_str(), hash ); + return hash; +} + + + + } // namespace Dali diff --git a/dali/internal/common/dali-hash.h b/dali/internal/common/dali-hash.h index 487efd3..a609762 100644 --- a/dali/internal/common/dali-hash.h +++ b/dali/internal/common/dali-hash.h @@ -22,10 +22,25 @@ namespace Dali { -struct StringHash -{ - unsigned long operator()(const std::string& toHash); -}; + +/** + * @brief Create a hash code for the string + * @param toHash string to hash + * @return hash code + */ +unsigned long CalculateHash(const std::string& toHash); + + +/** + * @brief Create a hash code for 2 strings combined + * @param string1 first string + * @param string2 second string + * @return hash code + */ +unsigned long CalculateHash(const std::string& string1, const std::string& string2); + + + } // namespace Dali diff --git a/dali/internal/event/effects/shader-factory.cpp b/dali/internal/event/effects/shader-factory.cpp index 6c488d3..5d7dc4c 100644 --- a/dali/internal/event/effects/shader-factory.cpp +++ b/dali/internal/event/effects/shader-factory.cpp @@ -61,7 +61,7 @@ ResourceTicketPtr ShaderFactory::Load(const std::string& vertexSource, const std { ResourceTicketPtr ticket; - shaderHash = HashShaderSource(vertexSource, fragmentSource); + shaderHash = CalculateHash(vertexSource, fragmentSource); std::stringstream stringHash; stringHash << shaderHash; std::string filename = DALI_SHADERBIN_DIR; @@ -211,19 +211,6 @@ void ShaderFactory::LoadTextSubtypeShaders(ShaderEffectPtr shaderEffect) } -size_t ShaderFactory::HashShaderSource(const std::string& vertexSource, const std::string& fragmentSource) const -{ - std::string source = vertexSource + fragmentSource; - - // remove all white spaces, tabs and new lines - source.erase(std::remove(source.begin(), source.end(), ' '), source.end()); - source.erase(std::remove(source.begin(), source.end(), '\n'), source.end()); - source.erase(std::remove(source.begin(), source.end(), '\t'), source.end()); - - StringHash hasher; - return hasher( source ); -} - } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/effects/shader-factory.h b/dali/internal/event/effects/shader-factory.h index 6da5ca4..2314c48 100644 --- a/dali/internal/event/effects/shader-factory.h +++ b/dali/internal/event/effects/shader-factory.h @@ -83,14 +83,6 @@ private: // Undefined ShaderFactory& operator=( const ShaderFactory& rhs ); - /** - * Returns a hash of the shader strings - * @param[in] vertexShaderSrc Source code for the vertex shader - * @param[in] fragmentShaderSrc Source code for the fragment shader - * @return Hashed value - */ - size_t HashShaderSource( const std::string& vertexShaderSrc, const std::string& fragmentShaderSrc ) const; - private: ResourceClient& mResourceClient; ResourceTypePathIdMap mResourceTypePathIdMap; ///< A map of resource IDs sorted by ResourceTypePath diff --git a/dali/internal/event/images/image-factory.cpp b/dali/internal/event/images/image-factory.cpp index c7e8f82..67e0895 100644 --- a/dali/internal/event/images/image-factory.cpp +++ b/dali/internal/event/images/image-factory.cpp @@ -60,8 +60,7 @@ Request* ImageFactory::RegisterRequest( const std::string &filename, const Image { // check url cache // check if same request exists - StringHash stringHashFunc; - std::size_t urlHash = stringHashFunc( filename ); + std::size_t urlHash = CalculateHash( filename ); Request* foundReq( NULL ); foundReq = FindRequest(filename, urlHash, attr); diff --git a/dali/internal/event/text/font-factory.cpp b/dali/internal/event/text/font-factory.cpp index 9b8ff20..c088d0f 100644 --- a/dali/internal/event/text/font-factory.cpp +++ b/dali/internal/event/text/font-factory.cpp @@ -25,8 +25,6 @@ #include #include -// EXTERNAL INCLUDES -#include using namespace Dali::Integration; @@ -57,8 +55,7 @@ FontFactory::~FontFactory() FontMetricsIntrusivePtr FontFactory::GetFontMetrics( const std::string& fontFamily, const std::string& fontStyle ) { - StringHash hasher; - std::size_t hashValue = hasher(fontFamily + fontStyle); + std::size_t hashValue = CalculateHash(fontFamily,fontStyle); FontMetricsIntrusivePtr metrics; FontMetricsIter iter = mMetricsCache.find( hashValue ); @@ -87,8 +84,7 @@ FontMetricsIntrusivePtr FontFactory::GetFontMetrics( const std::string& fontFami void FontFactory::RemoveFontMetrics(const std::string& fontFamily, const std::string& fontStyle) { - StringHash hasher; - std::size_t hashValue = hasher(fontFamily + fontStyle); + std::size_t hashValue = CalculateHash(fontFamily, fontStyle); FontMetricsIntrusivePtr metrics; FontMetricsIter iter = mMetricsCache.find( hashValue ); -- 2.7.4