summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/llhash.h15
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp176
-rw-r--r--indra/llmessage/llmessagethrottle.cpp4
-rw-r--r--indra/llprimitive/llprimitive.cpp13
-rw-r--r--indra/test/llblowfish_tut.cpp24
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
}
}