diff options
-rw-r--r-- | indra/llcommon/llhash.h | 15 | ||||
-rw-r--r-- | indra/llcommon/llsdserialize_xml.cpp | 176 | ||||
-rw-r--r-- | indra/llmessage/llmessagethrottle.cpp | 4 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.cpp | 13 | ||||
-rw-r--r-- | indra/test/llblowfish_tut.cpp | 24 |
5 files changed, 177 insertions, 55 deletions
diff --git a/indra/llcommon/llhash.h b/indra/llcommon/llhash.h index 08299f5ddc..ee327be8c9 100644 --- a/indra/llcommon/llhash.h +++ b/indra/llcommon/llhash.h @@ -53,15 +53,20 @@ #error Please define your platform. #endif -template<class T> inline size_t llhash(T value) -{ +// Warning - an earlier template-based version of this routine did not do +// the correct thing on Windows. Since this is only used to get +// a string hash, it was converted to a regular routine and +// unit tests added. + +inline size_t llhash( const char * value ) +{ #if LL_WINDOWS - return stdext::hash_value<T>(value); + return stdext::hash_value(value); #elif ( (defined _STLPORT_VERSION) || ((LL_LINUX) && (__GNUC__ <= 2)) ) - std::hash<T> H; + std::hash<const char *> H; return H(value); #elif LL_DARWIN || LL_LINUX || LL_SOLARIS - __gnu_cxx::hash<T> H; + __gnu_cxx::hash<const char *> H; return H(value); #else #error Please define your platform. diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index edcc244f58..ecb5b73fcd 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -318,8 +318,8 @@ private: bool mSkipping; int mSkipThrough; - std::string mCurrentKey; - std::ostringstream mCurrentContent; + std::string mCurrentKey; // Current XML <tag> + std::string mCurrentContent; // String data between <tag> and </tag> }; @@ -556,16 +556,50 @@ void LLSDXMLParser::Impl::parsePart(const char* buf, int len) } } +// Performance testing code +//#define XML_PARSER_PERFORMANCE_TESTS + +#ifdef XML_PARSER_PERFORMANCE_TESTS + +extern U64 totalTime(); +U64 readElementTime = 0; +U64 startElementTime = 0; +U64 endElementTime = 0; +U64 charDataTime = 0; +U64 parseTime = 0; + +class XML_Timer +{ +public: + XML_Timer( U64 * sum ) : mSum( sum ) + { + mStart = totalTime(); + } + ~XML_Timer() + { + *mSum += (totalTime() - mStart); + } + + U64 * mSum; + U64 mStart; +}; +#endif // XML_PARSER_PERFORMANCE_TESTS + void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Char** attributes) { + #ifdef XML_PARSER_PERFORMANCE_TESTS + XML_Timer timer( &startElementTime ); + #endif // XML_PARSER_PERFORMANCE_TESTS + ++mDepth; if (mSkipping) { return; } - + Element element = readElement(name); - mCurrentContent.str(""); + + mCurrentContent.clear(); switch (element) { @@ -645,6 +679,10 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) { + #ifdef XML_PARSER_PERFORMANCE_TESTS + XML_Timer timer( &endElementTime ); + #endif // XML_PARSER_PERFORMANCE_TESTS + --mDepth; if (mSkipping) { @@ -669,7 +707,7 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) return; case ELEMENT_KEY: - mCurrentKey = mCurrentContent.str(); + mCurrentKey = mCurrentContent; return; default: @@ -682,9 +720,6 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) LLSD& value = *mStack.back(); mStack.pop_back(); - std::string content = mCurrentContent.str(); - mCurrentContent.str(""); - switch (element) { case ELEMENT_UNDEF: @@ -692,39 +727,59 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) break; case ELEMENT_BOOL: - value = content == "true" || content == "1"; + value = (mCurrentContent == "true" || mCurrentContent == "1"); break; case ELEMENT_INTEGER: - value = LLSD(content).asInteger(); + { + S32 i; + if ( sscanf(mCurrentContent.c_str(), "%d", &i ) == 1 ) + { // See if sscanf works - it's faster + value = i; + } + else + { + value = LLSD(mCurrentContent).asInteger(); + } + } break; case ELEMENT_REAL: - value = LLSD(content).asReal(); + { + F64 r; + if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 ) + { // See if sscanf works - it's faster + value = r; + } + else + { + value = LLSD(mCurrentContent).asReal(); + } + } break; case ELEMENT_STRING: - value = content; + value = mCurrentContent; break; case ELEMENT_UUID: - value = LLSD(content).asUUID(); + value = LLSD(mCurrentContent).asUUID(); break; case ELEMENT_DATE: - value = LLSD(content).asDate(); + value = LLSD(mCurrentContent).asDate(); break; case ELEMENT_URI: - value = LLSD(content).asURI(); + value = LLSD(mCurrentContent).asURI(); break; case ELEMENT_BINARY: { - S32 len = apr_base64_decode_len(content.c_str()); + S32 len = apr_base64_decode_len(mCurrentContent.c_str()); std::vector<U8> data; data.resize(len); - len = apr_base64_decode_binary(&data[0], content.c_str()); + len = apr_base64_decode_binary(&data[0], mCurrentContent.c_str()); data.resize(len); value = data; break; @@ -738,11 +793,17 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) // other values, map and array, have already been set break; } + + mCurrentContent.clear(); } void LLSDXMLParser::Impl::characterDataHandler(const XML_Char* data, int length) { - mCurrentContent.write(data, length); + #ifdef XML_PARSER_PERFORMANCE_TESTS + XML_Timer timer( &charDataTime ); + #endif // XML_PARSER_PERFORMANCE_TESTS + + mCurrentContent.append(data, length); } @@ -765,22 +826,69 @@ void LLSDXMLParser::Impl::sCharacterDataHandler( } +/* + This code is time critical + + This is a sample of tag occurances of text in simstate file with ~8000 objects. + A tag pair (<key>something</key>) counts is counted as two: + + key - 2680178 + real - 1818362 + integer - 906078 + array - 295682 + map - 191818 + uuid - 177903 + binary - 175748 + string - 53482 + undef - 40353 + boolean - 33874 + llsd - 16332 + uri - 38 + date - 1 +*/ LLSDXMLParser::Impl::Element LLSDXMLParser::Impl::readElement(const XML_Char* name) { - if (strcmp(name, "llsd") == 0) { return ELEMENT_LLSD; } - if (strcmp(name, "undef") == 0) { return ELEMENT_UNDEF; } - if (strcmp(name, "boolean") == 0) { return ELEMENT_BOOL; } - if (strcmp(name, "integer") == 0) { return ELEMENT_INTEGER; } - if (strcmp(name, "real") == 0) { return ELEMENT_REAL; } - if (strcmp(name, "string") == 0) { return ELEMENT_STRING; } - if (strcmp(name, "uuid") == 0) { return ELEMENT_UUID; } - if (strcmp(name, "date") == 0) { return ELEMENT_DATE; } - if (strcmp(name, "uri") == 0) { return ELEMENT_URI; } - if (strcmp(name, "binary") == 0) { return ELEMENT_BINARY; } - if (strcmp(name, "map") == 0) { return ELEMENT_MAP; } - if (strcmp(name, "array") == 0) { return ELEMENT_ARRAY; } - if (strcmp(name, "key") == 0) { return ELEMENT_KEY; } - + #ifdef XML_PARSER_PERFORMANCE_TESTS + XML_Timer timer( &readElementTime ); + #endif // XML_PARSER_PERFORMANCE_TESTS + + XML_Char c = *name; + switch (c) + { + case 'k': + if (strcmp(name, "key") == 0) { return ELEMENT_KEY; } + break; + case 'r': + if (strcmp(name, "real") == 0) { return ELEMENT_REAL; } + break; + case 'i': + if (strcmp(name, "integer") == 0) { return ELEMENT_INTEGER; } + break; + case 'a': + if (strcmp(name, "array") == 0) { return ELEMENT_ARRAY; } + break; + case 'm': + if (strcmp(name, "map") == 0) { return ELEMENT_MAP; } + break; + case 'u': + if (strcmp(name, "uuid") == 0) { return ELEMENT_UUID; } + if (strcmp(name, "undef") == 0) { return ELEMENT_UNDEF; } + if (strcmp(name, "uri") == 0) { return ELEMENT_URI; } + break; + case 'b': + if (strcmp(name, "binary") == 0) { return ELEMENT_BINARY; } + if (strcmp(name, "boolean") == 0) { return ELEMENT_BOOL; } + break; + case 's': + if (strcmp(name, "string") == 0) { return ELEMENT_STRING; } + break; + case 'l': + if (strcmp(name, "llsd") == 0) { return ELEMENT_LLSD; } + break; + case 'd': + if (strcmp(name, "date") == 0) { return ELEMENT_DATE; } + break; + } return ELEMENT_UNKNOWN; } @@ -808,6 +916,10 @@ void LLSDXMLParser::parsePart(const char *buf, int len) // virtual S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data) const { + #ifdef XML_PARSER_PERFORMANCE_TESTS + XML_Timer timer( &parseTime ); + #endif // XML_PARSER_PERFORMANCE_TESTS + if (mParseLines) { // Use line-based reading (faster code) diff --git a/indra/llmessage/llmessagethrottle.cpp b/indra/llmessage/llmessagethrottle.cpp index 846d4067ad..db2cc28501 100644 --- a/indra/llmessage/llmessagethrottle.cpp +++ b/indra/llmessage/llmessagethrottle.cpp @@ -119,7 +119,7 @@ BOOL LLMessageThrottle::addViewerAlert(const LLUUID& to, const std::string& mesg full_mesg << to << mesg; // Create an entry for this message. - size_t hash = llhash<const char*> (full_mesg.str().c_str()); + size_t hash = llhash(full_mesg.str().c_str()); LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime()); // Check if this message is already in the list. @@ -153,7 +153,7 @@ BOOL LLMessageThrottle::addAgentAlert(const LLUUID& agent, const LLUUID& task, c full_mesg << agent << task << mesg; // Create an entry for this message. - size_t hash = llhash<const char*> (full_mesg.str().c_str()); + size_t hash = llhash(full_mesg.str().c_str()); LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime()); // Check if this message is already in the list. diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 90292d8f78..0039cca222 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -114,6 +114,11 @@ const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE; const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e"; +// Texture rotations are sent over the wire as a S16. This is used to scale the actual float +// value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it +// can't be divided by 2. See DEV-19108 +const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000); + //static // LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global // TODO -- eliminate this global from the codebase! @@ -1373,7 +1378,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const scale_t[face_index] = (F32) te->mScaleT; offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; - image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * (F32)0x7FFF)); + image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR)); bump[face_index] = te->getBumpShinyFullbright(); media_flags[face_index] = te->getMediaTexGen(); glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF)); @@ -1452,7 +1457,7 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const scale_t[face_index] = (F32) te->mScaleT; offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; - image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * (F32)0x7FFF)); + image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR)); bump[face_index] = te->getBumpShinyFullbright(); media_flags[face_index] = te->getMediaTexGen(); glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF)); @@ -1566,7 +1571,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, con retval |= setTETexture(i, ((LLUUID*)image_data)[i]); retval |= setTEScale(i, scale_s[i], scale_t[i]); retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); - retval |= setTERotation(i, ((F32)image_rot[i]/ (F32)0x7FFF) * F_TWO_PI); + retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); retval |= setTEBumpShinyFullbright(i, bump[i]); retval |= setTEMediaTexGen(i, media_flags[i]); retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); @@ -1660,7 +1665,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) retval |= setTETexture(i, image_ids[i]); retval |= setTEScale(i, scale_s[i], scale_t[i]); retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); - retval |= setTERotation(i, ((F32)image_rot[i]/ (F32)0x7FFF) * F_TWO_PI); + retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); retval |= setTEBumpShinyFullbright(i, bump[i]); retval |= setTEMediaTexGen(i, media_flags[i]); retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); diff --git a/indra/test/llblowfish_tut.cpp b/indra/test/llblowfish_tut.cpp index eb2e4ed0f8..97ed2be760 100644 --- a/indra/test/llblowfish_tut.cpp +++ b/indra/test/llblowfish_tut.cpp @@ -93,9 +93,7 @@ namespace tut template<> template<> void blowfish_object::test<1>() { -#if LL_WINDOWS - skip_fail("Blowfish only supported on Linux."); -#else +#if LL_LINUX LLUUID blank; LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES); @@ -108,15 +106,15 @@ namespace tut dst_len = cipher.requiredEncryptionSpace(8); ensure("encryption space 8", (dst_len == 16) ); -#endif // LL_WINDOWS +#else + skip_fail("Blowfish only supported on Linux."); +#endif // LL_LINUX } template<> template<> void blowfish_object::test<2>() { -#if LL_WINDOWS - skip_fail("Blowfish only supported on Linux."); -#else +#if LL_LINUX LLUUID blank; LLBlowfishCipher cipher(&blank.mData[0], UUID_BYTES); @@ -130,15 +128,15 @@ namespace tut result.resize(count); ensure("encrypt null key", matchFile("blowfish.1.bin", result)); -#endif // LL_WINDOWS +#else + skip_fail("Blowfish only supported on Linux."); +#endif // LL_LINUX } template<> template<> void blowfish_object::test<3>() { -#if LL_WINDOWS - skip_fail("Blowfish only supported on Linux."); -#else +#if LL_LINUX // same as base64 test id LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e"); LLBlowfishCipher cipher(&id.mData[0], UUID_BYTES); @@ -153,6 +151,8 @@ namespace tut result.resize(count); ensure("encrypt real key", matchFile("blowfish.2.bin", result)); -#endif // LL_WINDOWS +#else + skip_fail("Blowfish only supported on Linux."); +#endif // LL_LINUX } } |