diff options
Diffstat (limited to 'linden/indra/llcommon')
-rw-r--r-- | linden/indra/llcommon/CMakeLists.txt | 7 | ||||
-rw-r--r-- | linden/indra/llcommon/indra_constants.h | 1 | ||||
-rw-r--r-- | linden/indra/llcommon/llcommon.cpp | 4 | ||||
-rw-r--r-- | linden/indra/llcommon/llfasttimer.h | 1 | ||||
-rw-r--r-- | linden/indra/llcommon/llfindlocale.cpp | 4 | ||||
-rw-r--r-- | linden/indra/llcommon/llfindlocale.h | 4 | ||||
-rw-r--r-- | linden/indra/llcommon/llkeythrottle.h | 2 | ||||
-rw-r--r-- | linden/indra/llcommon/llprocessor.h | 20 | ||||
-rw-r--r-- | linden/indra/llcommon/llsdserialize.cpp | 2 | ||||
-rw-r--r-- | linden/indra/llcommon/llsdserialize_xml.cpp | 13 | ||||
-rw-r--r-- | linden/indra/llcommon/llstat.cpp | 562 | ||||
-rw-r--r-- | linden/indra/llcommon/llstat.h | 142 | ||||
-rw-r--r-- | linden/indra/llcommon/llstatenums.h | 17 | ||||
-rw-r--r-- | linden/indra/llcommon/llstl.h | 5 | ||||
-rw-r--r-- | linden/indra/llcommon/llstring.h | 37 | ||||
-rw-r--r-- | linden/indra/llcommon/llthread.cpp | 4 | ||||
-rw-r--r-- | linden/indra/llcommon/llthread.h | 4 | ||||
-rw-r--r-- | linden/indra/llcommon/lltimer.cpp | 53 | ||||
-rw-r--r-- | linden/indra/llcommon/lltimer.h | 5 | ||||
-rw-r--r-- | linden/indra/llcommon/llversionserver.h | 4 | ||||
-rw-r--r-- | linden/indra/llcommon/llversionviewer.h | 4 |
21 files changed, 743 insertions, 152 deletions
diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt index 8810549..4001e1f 100644 --- a/linden/indra/llcommon/CMakeLists.txt +++ b/linden/indra/llcommon/CMakeLists.txt | |||
@@ -187,3 +187,10 @@ set_source_files_properties(${llcommon_HEADER_FILES} | |||
187 | list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) | 187 | list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) |
188 | 188 | ||
189 | add_library (llcommon ${llcommon_SOURCE_FILES}) | 189 | add_library (llcommon ${llcommon_SOURCE_FILES}) |
190 | target_link_libraries( | ||
191 | llcommon | ||
192 | ${APRUTIL_LIBRARIES} | ||
193 | ${APR_LIBRARIES} | ||
194 | ${EXPAT_LIBRARIES} | ||
195 | ${ZLIB_LIBRARIES} | ||
196 | ) | ||
diff --git a/linden/indra/llcommon/indra_constants.h b/linden/indra/llcommon/indra_constants.h index 1c48a5c..fcb2aaf 100644 --- a/linden/indra/llcommon/indra_constants.h +++ b/linden/indra/llcommon/indra_constants.h | |||
@@ -251,6 +251,7 @@ const U8 GOD_NOT = 0; | |||
251 | const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb"); | 251 | const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb"); |
252 | 252 | ||
253 | // Governor Linden's agent id. | 253 | // Governor Linden's agent id. |
254 | const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f"); | ||
254 | const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); | 255 | const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); |
255 | const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); | 256 | const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); |
256 | // Maintenance's group id. | 257 | // Maintenance's group id. |
diff --git a/linden/indra/llcommon/llcommon.cpp b/linden/indra/llcommon/llcommon.cpp index b21b687..cdaa7f9 100644 --- a/linden/indra/llcommon/llcommon.cpp +++ b/linden/indra/llcommon/llcommon.cpp | |||
@@ -46,7 +46,7 @@ void LLCommon::initClass() | |||
46 | sAprInitialized = TRUE; | 46 | sAprInitialized = TRUE; |
47 | } | 47 | } |
48 | LLTimer::initClass(); | 48 | LLTimer::initClass(); |
49 | LLThreadSafeRefCount::initClass(); | 49 | LLThreadSafeRefCount::initThreadSafeRefCount(); |
50 | // LLWorkerThread::initClass(); | 50 | // LLWorkerThread::initClass(); |
51 | // LLFrameCallbackManager::initClass(); | 51 | // LLFrameCallbackManager::initClass(); |
52 | } | 52 | } |
@@ -56,7 +56,7 @@ void LLCommon::cleanupClass() | |||
56 | { | 56 | { |
57 | // LLFrameCallbackManager::cleanupClass(); | 57 | // LLFrameCallbackManager::cleanupClass(); |
58 | // LLWorkerThread::cleanupClass(); | 58 | // LLWorkerThread::cleanupClass(); |
59 | LLThreadSafeRefCount::cleanupClass(); | 59 | LLThreadSafeRefCount::cleanupThreadSafeRefCount(); |
60 | LLTimer::cleanupClass(); | 60 | LLTimer::cleanupClass(); |
61 | if (sAprInitialized) | 61 | if (sAprInitialized) |
62 | { | 62 | { |
diff --git a/linden/indra/llcommon/llfasttimer.h b/linden/indra/llcommon/llfasttimer.h index 8ad2667..80ed26b 100644 --- a/linden/indra/llcommon/llfasttimer.h +++ b/linden/indra/llcommon/llfasttimer.h | |||
@@ -165,6 +165,7 @@ public: | |||
165 | FTM_FILTER, | 165 | FTM_FILTER, |
166 | FTM_REFRESH, | 166 | FTM_REFRESH, |
167 | FTM_SORT, | 167 | FTM_SORT, |
168 | FTM_PICK, | ||
168 | 169 | ||
169 | // Temp | 170 | // Temp |
170 | FTM_TEMP1, | 171 | FTM_TEMP1, |
diff --git a/linden/indra/llcommon/llfindlocale.cpp b/linden/indra/llcommon/llfindlocale.cpp index 47da974..344041c 100644 --- a/linden/indra/llcommon/llfindlocale.cpp +++ b/linden/indra/llcommon/llfindlocale.cpp | |||
@@ -180,10 +180,10 @@ canonise_fl(FL_Locale *l) { | |||
180 | #define ML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##pn##_##sn) | 180 | #define ML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##pn##_##sn) |
181 | #define MLN(pn) MAKELANGID(LANG_##pn, SUBLANG_DEFAULT) | 181 | #define MLN(pn) MAKELANGID(LANG_##pn, SUBLANG_DEFAULT) |
182 | #define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn) | 182 | #define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn) |
183 | typedef struct { | 183 | struct IDToCode { |
184 | LANGID id; | 184 | LANGID id; |
185 | char* code; | 185 | char* code; |
186 | } IDToCode; | 186 | }; |
187 | static const IDToCode both_to_code[] = { | 187 | static const IDToCode both_to_code[] = { |
188 | {ML(ENGLISH,US), "en_US.ISO_8859-1"}, | 188 | {ML(ENGLISH,US), "en_US.ISO_8859-1"}, |
189 | {ML(ENGLISH,CAN), "en_CA"}, /* english / canadian */ | 189 | {ML(ENGLISH,CAN), "en_CA"}, /* english / canadian */ |
diff --git a/linden/indra/llcommon/llfindlocale.h b/linden/indra/llcommon/llfindlocale.h index 6cc2dbb..bc253c3 100644 --- a/linden/indra/llcommon/llfindlocale.h +++ b/linden/indra/llcommon/llfindlocale.h | |||
@@ -36,11 +36,11 @@ typedef const char* FL_Lang; | |||
36 | typedef const char* FL_Country; | 36 | typedef const char* FL_Country; |
37 | typedef const char* FL_Variant; | 37 | typedef const char* FL_Variant; |
38 | 38 | ||
39 | typedef struct { | 39 | struct FL_Locale { |
40 | FL_Lang lang; | 40 | FL_Lang lang; |
41 | FL_Country country; | 41 | FL_Country country; |
42 | FL_Variant variant; | 42 | FL_Variant variant; |
43 | } FL_Locale; | 43 | }; |
44 | 44 | ||
45 | typedef enum { | 45 | typedef enum { |
46 | /* for some reason we failed to even guess: this should never happen */ | 46 | /* for some reason we failed to even guess: this should never happen */ |
diff --git a/linden/indra/llcommon/llkeythrottle.h b/linden/indra/llcommon/llkeythrottle.h index eb1519a..25d0fe0 100644 --- a/linden/indra/llcommon/llkeythrottle.h +++ b/linden/indra/llcommon/llkeythrottle.h | |||
@@ -243,7 +243,7 @@ public: | |||
243 | } | 243 | } |
244 | 244 | ||
245 | // Set the throttling behavior | 245 | // Set the throttling behavior |
246 | void setParameters( U32 limit, F32 interval, BOOL realtime ) | 246 | void setParameters( U32 limit, F32 interval, BOOL realtime = TRUE ) |
247 | { | 247 | { |
248 | // limit is the maximum number of keys | 248 | // limit is the maximum number of keys |
249 | // allowed per interval (in seconds or frames) | 249 | // allowed per interval (in seconds or frames) |
diff --git a/linden/indra/llcommon/llprocessor.h b/linden/indra/llcommon/llprocessor.h index 6abbd96..06dc72a 100644 --- a/linden/indra/llcommon/llprocessor.h +++ b/linden/indra/llcommon/llprocessor.h | |||
@@ -58,7 +58,7 @@ | |||
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | 60 | ||
61 | typedef struct ProcessorExtensions | 61 | struct ProcessorExtensions |
62 | { | 62 | { |
63 | bool FPU_FloatingPointUnit; | 63 | bool FPU_FloatingPointUnit; |
64 | bool VME_Virtual8086ModeEnhancements; | 64 | bool VME_Virtual8086ModeEnhancements; |
@@ -97,9 +97,9 @@ typedef struct ProcessorExtensions | |||
97 | bool _3DNOW_InstructionExtensions; | 97 | bool _3DNOW_InstructionExtensions; |
98 | bool _E3DNOW_InstructionExtensions; | 98 | bool _E3DNOW_InstructionExtensions; |
99 | bool AA64_AMD64BitArchitecture; | 99 | bool AA64_AMD64BitArchitecture; |
100 | } ProcessorExtensions; | 100 | }; |
101 | 101 | ||
102 | typedef struct ProcessorCache | 102 | struct ProcessorCache |
103 | { | 103 | { |
104 | bool bPresent; | 104 | bool bPresent; |
105 | char strSize[32]; /* Flawfinder: ignore */ | 105 | char strSize[32]; /* Flawfinder: ignore */ |
@@ -107,24 +107,24 @@ typedef struct ProcessorCache | |||
107 | unsigned int uiLineSize; | 107 | unsigned int uiLineSize; |
108 | bool bSectored; | 108 | bool bSectored; |
109 | char strCache[128]; /* Flawfinder: ignore */ | 109 | char strCache[128]; /* Flawfinder: ignore */ |
110 | } ProcessorCache; | 110 | }; |
111 | 111 | ||
112 | typedef struct ProcessorL1Cache | 112 | struct ProcessorL1Cache |
113 | { | 113 | { |
114 | ProcessorCache Instruction; | 114 | ProcessorCache Instruction; |
115 | ProcessorCache Data; | 115 | ProcessorCache Data; |
116 | } ProcessorL1Cache; | 116 | }; |
117 | 117 | ||
118 | typedef struct ProcessorTLB | 118 | struct ProcessorTLB |
119 | { | 119 | { |
120 | bool bPresent; | 120 | bool bPresent; |
121 | char strPageSize[32]; /* Flawfinder: ignore */ | 121 | char strPageSize[32]; /* Flawfinder: ignore */ |
122 | unsigned int uiAssociativeWays; | 122 | unsigned int uiAssociativeWays; |
123 | unsigned int uiEntries; | 123 | unsigned int uiEntries; |
124 | char strTLB[128]; /* Flawfinder: ignore */ | 124 | char strTLB[128]; /* Flawfinder: ignore */ |
125 | } ProcessorTLB; | 125 | }; |
126 | 126 | ||
127 | typedef struct ProcessorInfo | 127 | struct ProcessorInfo |
128 | { | 128 | { |
129 | char strVendor[16]; /* Flawfinder: ignore */ | 129 | char strVendor[16]; /* Flawfinder: ignore */ |
130 | unsigned int uiFamily; | 130 | unsigned int uiFamily; |
@@ -148,7 +148,7 @@ typedef struct ProcessorInfo | |||
148 | ProcessorCache _Trace; | 148 | ProcessorCache _Trace; |
149 | ProcessorTLB _Instruction; | 149 | ProcessorTLB _Instruction; |
150 | ProcessorTLB _Data; | 150 | ProcessorTLB _Data; |
151 | } ProcessorInfo; | 151 | }; |
152 | 152 | ||
153 | 153 | ||
154 | // CProcessor | 154 | // CProcessor |
diff --git a/linden/indra/llcommon/llsdserialize.cpp b/linden/indra/llcommon/llsdserialize.cpp index d42842d..f21ff68 100644 --- a/linden/indra/llcommon/llsdserialize.cpp +++ b/linden/indra/llcommon/llsdserialize.cpp | |||
@@ -324,7 +324,7 @@ S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes) | |||
324 | S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) | 324 | S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) |
325 | { | 325 | { |
326 | mCheckLimits = false; | 326 | mCheckLimits = false; |
327 | mParseLines = false; // was true, Emergency fix DEV-17785 parsing newline failure | 327 | mParseLines = true; |
328 | return doParse(istr, data); | 328 | return doParse(istr, data); |
329 | } | 329 | } |
330 | 330 | ||
diff --git a/linden/indra/llcommon/llsdserialize_xml.cpp b/linden/indra/llcommon/llsdserialize_xml.cpp index 690ab67..9c3f85e 100644 --- a/linden/indra/llcommon/llsdserialize_xml.cpp +++ b/linden/indra/llcommon/llsdserialize_xml.cpp | |||
@@ -461,11 +461,11 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data) | |||
461 | input.clear(); | 461 | input.clear(); |
462 | } | 462 | } |
463 | 463 | ||
464 | // Don't parse the NULL at the end which might be added if \n was absorbed by getline() | 464 | // Re-insert with the \n that was absorbed by getline() |
465 | char * text = (char *) buffer; | 465 | char * text = (char *) buffer; |
466 | if ( text[num_read - 1] == 0) | 466 | if ( text[num_read - 1] == 0) |
467 | { | 467 | { |
468 | num_read--; | 468 | text[num_read - 1] = '\n'; |
469 | } | 469 | } |
470 | } | 470 | } |
471 | 471 | ||
@@ -808,12 +808,11 @@ void LLSDXMLParser::parsePart(const char *buf, int len) | |||
808 | // virtual | 808 | // virtual |
809 | S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data) const | 809 | S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data) const |
810 | { | 810 | { |
811 | // Remove code - emergency fix DEV-17785 parsing newline failure | 811 | if (mParseLines) |
812 | // if (mParseLines) | 812 | { |
813 | // { | ||
814 | // Use line-based reading (faster code) | 813 | // Use line-based reading (faster code) |
815 | // return impl.parseLines(input, data); | 814 | return impl.parseLines(input, data); |
816 | // } | 815 | } |
817 | 816 | ||
818 | return impl.parse(input, data); | 817 | return impl.parse(input, data); |
819 | } | 818 | } |
diff --git a/linden/indra/llcommon/llstat.cpp b/linden/indra/llcommon/llstat.cpp index 4b79fcb..706acdb 100644 --- a/linden/indra/llcommon/llstat.cpp +++ b/linden/indra/llcommon/llstat.cpp | |||
@@ -31,55 +31,288 @@ | |||
31 | #include "linden_common.h" | 31 | #include "linden_common.h" |
32 | 32 | ||
33 | #include "llstat.h" | 33 | #include "llstat.h" |
34 | #include "lllivefile.h" | ||
35 | #include "llerrorcontrol.h" | ||
34 | #include "llframetimer.h" | 36 | #include "llframetimer.h" |
35 | #include "timing.h" | 37 | #include "timing.h" |
38 | #include "llsd.h" | ||
39 | #include "llsdserialize.h" | ||
40 | #include "llstl.h" | ||
41 | #include "u64.h" | ||
36 | 42 | ||
37 | class LLStatAccum::impl | 43 | |
44 | // statics | ||
45 | BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information | ||
46 | LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects | ||
47 | std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step" | ||
48 | |||
49 | //------------------------------------------------------------------------ | ||
50 | // Live config file to trigger stats logging | ||
51 | static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd"; | ||
52 | static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds | ||
53 | |||
54 | class LLStatsConfigFile : public LLLiveFile | ||
38 | { | 55 | { |
39 | public: | 56 | public: |
40 | static const TimeScale IMPL_NUM_SCALES = (TimeScale)(SCALE_TWO_MINUTE + 1); | 57 | LLStatsConfigFile() |
41 | static U64 sScaleTimes[IMPL_NUM_SCALES]; | 58 | : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE), |
59 | mChanged(false), mStatsp(NULL) { } | ||
42 | 60 | ||
43 | BOOL mUseFrameTimer; | 61 | static std::string filename(); |
62 | |||
63 | protected: | ||
64 | /* virtual */ void loadFile(); | ||
44 | 65 | ||
45 | BOOL mRunning; | 66 | public: |
46 | U64 mLastTime; | 67 | void init(LLPerfStats* statsp); |
47 | 68 | static LLStatsConfigFile& instance(); | |
48 | struct Bucket | 69 | // return the singleton stats config file |
49 | { | ||
50 | F64 accum; | ||
51 | U64 endTime; | ||
52 | 70 | ||
53 | BOOL lastValid; | 71 | bool mChanged; |
54 | F64 lastAccum; | ||
55 | }; | ||
56 | 72 | ||
57 | Bucket mBuckets[IMPL_NUM_SCALES]; | 73 | protected: |
74 | LLPerfStats* mStatsp; | ||
75 | }; | ||
58 | 76 | ||
59 | BOOL mLastSampleValid; | 77 | std::string LLStatsConfigFile::filename() |
60 | F64 mLastSampleValue; | 78 | { |
79 | return STATS_CONFIG_FILE_NAME; | ||
80 | } | ||
61 | 81 | ||
82 | void LLStatsConfigFile::init(LLPerfStats* statsp) | ||
83 | { | ||
84 | mStatsp = statsp; | ||
85 | } | ||
62 | 86 | ||
63 | impl(bool useFrameTimer); | 87 | LLStatsConfigFile& LLStatsConfigFile::instance() |
88 | { | ||
89 | static LLStatsConfigFile the_file; | ||
90 | return the_file; | ||
91 | } | ||
64 | 92 | ||
65 | void reset(U64 when); | ||
66 | 93 | ||
67 | void sum(F64 value); | 94 | /* virtual */ |
68 | void sum(F64 value, U64 when); | 95 | // Load and parse the stats configuration file |
96 | void LLStatsConfigFile::loadFile() | ||
97 | { | ||
98 | if (!mStatsp) | ||
99 | { | ||
100 | llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl; | ||
101 | return; | ||
102 | } | ||
103 | mChanged = true; | ||
104 | |||
105 | LLSD stats_config; | ||
106 | { | ||
107 | llifstream file(filename().c_str()); | ||
108 | if (file.is_open()) | ||
109 | { | ||
110 | LLSDSerialize::fromXML(stats_config, file); | ||
111 | if (stats_config.isUndefined()) | ||
112 | { | ||
113 | llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl; | ||
114 | mStatsp->setReportPerformanceDuration( 0.f ); | ||
115 | return; | ||
116 | } | ||
117 | } | ||
118 | else | ||
119 | { // File went away, turn off stats if it was on | ||
120 | if ( mStatsp->frameStatsIsRunning() ) | ||
121 | { | ||
122 | llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl; | ||
123 | mStatsp->setReportPerformanceDuration( 0.f ); | ||
124 | } | ||
125 | return; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | F32 duration = 0.f; | ||
130 | F32 interval = 0.f; | ||
131 | |||
132 | const char * w = "duration"; | ||
133 | if (stats_config.has(w)) | ||
134 | { | ||
135 | duration = (F32)stats_config[w].asReal(); | ||
136 | } | ||
137 | w = "interval"; | ||
138 | if (stats_config.has(w)) | ||
139 | { | ||
140 | interval = (F32)stats_config[w].asReal(); | ||
141 | } | ||
142 | |||
143 | mStatsp->setReportPerformanceDuration( duration ); | ||
144 | mStatsp->setReportPerformanceInterval( interval ); | ||
145 | |||
146 | if ( duration > 0 ) | ||
147 | { | ||
148 | if ( interval == 0.f ) | ||
149 | { | ||
150 | llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl; | ||
151 | } | ||
152 | else | ||
153 | { | ||
154 | llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl; | ||
155 | } | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | llinfos << "Performance stats recording turned off" << llendl; | ||
160 | } | ||
161 | } | ||
69 | 162 | ||
70 | F32 meanValue(TimeScale scale) const; | ||
71 | 163 | ||
72 | U64 getCurrentUsecs() const; | 164 | //------------------------------------------------------------------------ |
73 | // Get current microseconds based on timer type | ||
74 | }; | ||
75 | 165 | ||
166 | LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) : | ||
167 | mFrameStatsFileFailure(FALSE), | ||
168 | mSkipFirstFrameStats(FALSE), | ||
169 | mProcessName(process_name), | ||
170 | mProcessPID(process_pid), | ||
171 | mReportPerformanceStatInterval(1.f), | ||
172 | mReportPerformanceStatEnd(0.0) | ||
173 | { } | ||
76 | 174 | ||
77 | U64 LLStatAccum::impl::sScaleTimes[IMPL_NUM_SCALES] = | 175 | LLPerfStats::~LLPerfStats() |
176 | { | ||
177 | LLPerfBlock::clearDynamicStats(); | ||
178 | mFrameStatsFile.close(); | ||
179 | } | ||
180 | |||
181 | void LLPerfStats::init() | ||
182 | { | ||
183 | // Initialize the stats config file instance. | ||
184 | (void) LLStatsConfigFile::instance().init(this); | ||
185 | (void) LLStatsConfigFile::instance().checkAndReload(); | ||
186 | } | ||
187 | |||
188 | // Open file for statistics | ||
189 | void LLPerfStats::openPerfStatsFile() | ||
190 | { | ||
191 | if ( !mFrameStatsFile | ||
192 | && !mFrameStatsFileFailure ) | ||
193 | { | ||
194 | std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID); | ||
195 | mFrameStatsFile.close(); | ||
196 | mFrameStatsFile.clear(); | ||
197 | mFrameStatsFile.open(stats_file, llofstream::out); | ||
198 | if ( mFrameStatsFile.fail() ) | ||
199 | { | ||
200 | llinfos << "Error opening statistics log file " << stats_file << llendl; | ||
201 | mFrameStatsFileFailure = TRUE; | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | LLSD process_info = LLSD::emptyMap(); | ||
206 | process_info["name"] = mProcessName; | ||
207 | process_info["pid"] = (LLSD::Integer) mProcessPID; | ||
208 | process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval; | ||
209 | // Add process-specific info. | ||
210 | addProcessHeaderInfo(process_info); | ||
211 | |||
212 | mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | // Dump out performance metrics over some time interval | ||
218 | void LLPerfStats::dumpIntervalPerformanceStats() | ||
219 | { | ||
220 | // Ensure output file is OK | ||
221 | openPerfStatsFile(); | ||
222 | |||
223 | if ( mFrameStatsFile ) | ||
224 | { | ||
225 | LLSD stats = LLSD::emptyMap(); | ||
226 | |||
227 | LLStatAccum::TimeScale scale; | ||
228 | if ( getReportPerformanceInterval() == 0.f ) | ||
229 | { | ||
230 | scale = LLStatAccum::SCALE_PER_FRAME; | ||
231 | } | ||
232 | else if ( getReportPerformanceInterval() < 0.5f ) | ||
233 | { | ||
234 | scale = LLStatAccum::SCALE_100MS; | ||
235 | } | ||
236 | else | ||
237 | { | ||
238 | scale = LLStatAccum::SCALE_SECOND; | ||
239 | } | ||
240 | |||
241 | // Write LLSD into log | ||
242 | stats["utc_time"] = (LLSD::String) LLError::utcTime(); | ||
243 | stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch | ||
244 | stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount(); | ||
245 | |||
246 | // Add process-specific frame info. | ||
247 | addProcessFrameInfo(stats, scale); | ||
248 | LLPerfBlock::addStatsToLLSDandReset( stats, scale ); | ||
249 | |||
250 | mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | // Set length of performance stat recording | ||
255 | void LLPerfStats::setReportPerformanceDuration( F32 seconds ) | ||
256 | { | ||
257 | if ( seconds <= 0.f ) | ||
258 | { | ||
259 | mReportPerformanceStatEnd = 0.0; | ||
260 | LLPerfBlock::setStatsEnabled( FALSE ); | ||
261 | mFrameStatsFile.close(); | ||
262 | LLPerfBlock::clearDynamicStats(); | ||
263 | } | ||
264 | else | ||
265 | { | ||
266 | mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds); | ||
267 | // Clear failure flag to try and create the log file once | ||
268 | mFrameStatsFileFailure = FALSE; | ||
269 | LLPerfBlock::setStatsEnabled( TRUE ); | ||
270 | mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame) | ||
271 | } | ||
272 | } | ||
273 | |||
274 | void LLPerfStats::updatePerFrameStats() | ||
275 | { | ||
276 | (void) LLStatsConfigFile::instance().checkAndReload(); | ||
277 | static LLFrameTimer performance_stats_timer; | ||
278 | if ( frameStatsIsRunning() ) | ||
279 | { | ||
280 | if ( mReportPerformanceStatInterval == 0 ) | ||
281 | { // Record info every frame | ||
282 | if ( mSkipFirstFrameStats ) | ||
283 | { // Skip the first time - was started this frame | ||
284 | mSkipFirstFrameStats = FALSE; | ||
285 | } | ||
286 | else | ||
287 | { | ||
288 | dumpIntervalPerformanceStats(); | ||
289 | } | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() ); | ||
294 | if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval )) | ||
295 | { | ||
296 | dumpIntervalPerformanceStats(); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd ) | ||
301 | { // Reached end of time, clear it to stop reporting | ||
302 | setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly | ||
303 | llinfos << "Recording performance stats completed" << llendl; | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | |||
308 | |||
309 | //------------------------------------------------------------------------ | ||
310 | |||
311 | U64 LLStatAccum::sScaleTimes[NUM_SCALES] = | ||
78 | { | 312 | { |
79 | USEC_PER_SEC / 10, // 100 millisec | 313 | USEC_PER_SEC / 10, // 100 millisec |
80 | USEC_PER_SEC * 1, // seconds | 314 | USEC_PER_SEC * 1, // seconds |
81 | USEC_PER_SEC * 60, // minutes | 315 | USEC_PER_SEC * 60, // minutes |
82 | USEC_PER_SEC * 60 * 2 // two minutes | ||
83 | #if ENABLE_LONG_TIME_STATS | 316 | #if ENABLE_LONG_TIME_STATS |
84 | // enable these when more time scales are desired | 317 | // enable these when more time scales are desired |
85 | USEC_PER_SEC * 60*60, // hours | 318 | USEC_PER_SEC * 60*60, // hours |
@@ -89,19 +322,27 @@ U64 LLStatAccum::impl::sScaleTimes[IMPL_NUM_SCALES] = | |||
89 | }; | 322 | }; |
90 | 323 | ||
91 | 324 | ||
92 | LLStatAccum::impl::impl(bool useFrameTimer) | 325 | |
326 | LLStatAccum::LLStatAccum(bool useFrameTimer) | ||
327 | : mUseFrameTimer(useFrameTimer), | ||
328 | mRunning(FALSE), | ||
329 | mLastSampleValue(0.0), | ||
330 | mLastSampleValid(FALSE) | ||
331 | { | ||
332 | } | ||
333 | |||
334 | LLStatAccum::~LLStatAccum() | ||
93 | { | 335 | { |
94 | mUseFrameTimer = useFrameTimer; | ||
95 | mRunning = FALSE; | ||
96 | mLastSampleValid = FALSE; | ||
97 | } | 336 | } |
98 | 337 | ||
99 | void LLStatAccum::impl::reset(U64 when) | 338 | |
339 | |||
340 | void LLStatAccum::reset(U64 when) | ||
100 | { | 341 | { |
101 | mRunning = TRUE; | 342 | mRunning = TRUE; |
102 | mLastTime = when; | 343 | mLastTime = when; |
103 | 344 | ||
104 | for (int i = 0; i < IMPL_NUM_SCALES; ++i) | 345 | for (int i = 0; i < NUM_SCALES; ++i) |
105 | { | 346 | { |
106 | mBuckets[i].accum = 0.0; | 347 | mBuckets[i].accum = 0.0; |
107 | mBuckets[i].endTime = when + sScaleTimes[i]; | 348 | mBuckets[i].endTime = when + sScaleTimes[i]; |
@@ -109,12 +350,12 @@ void LLStatAccum::impl::reset(U64 when) | |||
109 | } | 350 | } |
110 | } | 351 | } |
111 | 352 | ||
112 | void LLStatAccum::impl::sum(F64 value) | 353 | void LLStatAccum::sum(F64 value) |
113 | { | 354 | { |
114 | sum(value, getCurrentUsecs()); | 355 | sum(value, getCurrentUsecs()); |
115 | } | 356 | } |
116 | 357 | ||
117 | void LLStatAccum::impl::sum(F64 value, U64 when) | 358 | void LLStatAccum::sum(F64 value, U64 when) |
118 | { | 359 | { |
119 | if (!mRunning) | 360 | if (!mRunning) |
120 | { | 361 | { |
@@ -131,7 +372,10 @@ void LLStatAccum::impl::sum(F64 value, U64 when) | |||
131 | return; | 372 | return; |
132 | } | 373 | } |
133 | 374 | ||
134 | for (int i = 0; i < IMPL_NUM_SCALES; ++i) | 375 | // how long is this value for |
376 | U64 timeSpan = when - mLastTime; | ||
377 | |||
378 | for (int i = 0; i < NUM_SCALES; ++i) | ||
135 | { | 379 | { |
136 | Bucket& bucket = mBuckets[i]; | 380 | Bucket& bucket = mBuckets[i]; |
137 | 381 | ||
@@ -143,8 +387,6 @@ void LLStatAccum::impl::sum(F64 value, U64 when) | |||
143 | { | 387 | { |
144 | U64 timeScale = sScaleTimes[i]; | 388 | U64 timeScale = sScaleTimes[i]; |
145 | 389 | ||
146 | U64 timeSpan = when - mLastTime; | ||
147 | // how long is this value for | ||
148 | U64 timeLeft = when - bucket.endTime; | 390 | U64 timeLeft = when - bucket.endTime; |
149 | // how much time is left after filling this bucket | 391 | // how much time is left after filling this bucket |
150 | 392 | ||
@@ -173,13 +415,18 @@ void LLStatAccum::impl::sum(F64 value, U64 when) | |||
173 | } | 415 | } |
174 | 416 | ||
175 | 417 | ||
176 | F32 LLStatAccum::impl::meanValue(TimeScale scale) const | 418 | F32 LLStatAccum::meanValue(TimeScale scale) const |
177 | { | 419 | { |
178 | if (!mRunning) | 420 | if (!mRunning) |
179 | { | 421 | { |
180 | return 0.0; | 422 | return 0.0; |
181 | } | 423 | } |
182 | if (scale < 0 || scale >= IMPL_NUM_SCALES) | 424 | if ( scale == SCALE_PER_FRAME ) |
425 | { // Per-frame not supported here | ||
426 | scale = SCALE_100MS; | ||
427 | } | ||
428 | |||
429 | if (scale < 0 || scale >= NUM_SCALES) | ||
183 | { | 430 | { |
184 | llwarns << "llStatAccum::meanValue called for unsupported scale: " | 431 | llwarns << "llStatAccum::meanValue called for unsupported scale: " |
185 | << scale << llendl; | 432 | << scale << llendl; |
@@ -209,7 +456,7 @@ F32 LLStatAccum::impl::meanValue(TimeScale scale) const | |||
209 | } | 456 | } |
210 | 457 | ||
211 | 458 | ||
212 | U64 LLStatAccum::impl::getCurrentUsecs() const | 459 | U64 LLStatAccum::getCurrentUsecs() const |
213 | { | 460 | { |
214 | if (mUseFrameTimer) | 461 | if (mUseFrameTimer) |
215 | { | 462 | { |
@@ -222,25 +469,44 @@ U64 LLStatAccum::impl::getCurrentUsecs() const | |||
222 | } | 469 | } |
223 | 470 | ||
224 | 471 | ||
472 | // ------------------------------------------------------------------------ | ||
225 | 473 | ||
226 | 474 | LLStatRate::LLStatRate(bool use_frame_timer) | |
227 | 475 | : LLStatAccum(use_frame_timer) | |
228 | LLStatAccum::LLStatAccum(bool useFrameTimer) | ||
229 | : m(* new impl(useFrameTimer)) | ||
230 | { | 476 | { |
231 | } | 477 | } |
232 | 478 | ||
233 | LLStatAccum::~LLStatAccum() | 479 | void LLStatRate::count(U32 value) |
234 | { | 480 | { |
235 | delete &m; | 481 | sum((F64)value * sScaleTimes[SCALE_SECOND]); |
236 | } | 482 | } |
237 | 483 | ||
238 | F32 LLStatAccum::meanValue(TimeScale scale) const | 484 | |
239 | { | 485 | void LLStatRate::mark() |
240 | return m.meanValue(scale); | 486 | { |
241 | } | 487 | // Effectively the same as count(1), but sets mLastSampleValue |
488 | U64 when = getCurrentUsecs(); | ||
489 | |||
490 | if ( mRunning | ||
491 | && (when > mLastTime) ) | ||
492 | { // Set mLastSampleValue to the time from the last mark() | ||
493 | F64 duration = ((F64)(when - mLastTime)) / sScaleTimes[SCALE_SECOND]; | ||
494 | if ( duration > 0.0 ) | ||
495 | { | ||
496 | mLastSampleValue = 1.0 / duration; | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | mLastSampleValue = 0.0; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | sum( (F64) sScaleTimes[SCALE_SECOND], when); | ||
505 | } | ||
242 | 506 | ||
243 | 507 | ||
508 | // ------------------------------------------------------------------------ | ||
509 | |||
244 | 510 | ||
245 | LLStatMeasure::LLStatMeasure(bool use_frame_timer) | 511 | LLStatMeasure::LLStatMeasure(bool use_frame_timer) |
246 | : LLStatAccum(use_frame_timer) | 512 | : LLStatAccum(use_frame_timer) |
@@ -249,53 +515,209 @@ LLStatMeasure::LLStatMeasure(bool use_frame_timer) | |||
249 | 515 | ||
250 | void LLStatMeasure::sample(F64 value) | 516 | void LLStatMeasure::sample(F64 value) |
251 | { | 517 | { |
252 | U64 when = m.getCurrentUsecs(); | 518 | U64 when = getCurrentUsecs(); |
253 | 519 | ||
254 | if (m.mLastSampleValid) | 520 | if (mLastSampleValid) |
255 | { | 521 | { |
256 | F64 avgValue = (value + m.mLastSampleValue) / 2.0; | 522 | F64 avgValue = (value + mLastSampleValue) / 2.0; |
257 | F64 interval = (F64)(when - m.mLastTime); | 523 | F64 interval = (F64)(when - mLastTime); |
258 | 524 | ||
259 | m.sum(avgValue * interval, when); | 525 | sum(avgValue * interval, when); |
260 | } | 526 | } |
261 | else | 527 | else |
262 | { | 528 | { |
263 | m.reset(when); | 529 | reset(when); |
264 | } | 530 | } |
265 | 531 | ||
266 | m.mLastSampleValid = TRUE; | 532 | mLastSampleValid = TRUE; |
267 | m.mLastSampleValue = value; | 533 | mLastSampleValue = value; |
268 | } | 534 | } |
269 | 535 | ||
270 | 536 | ||
271 | LLStatRate::LLStatRate(bool use_frame_timer) | 537 | // ------------------------------------------------------------------------ |
272 | : LLStatAccum(use_frame_timer) | 538 | |
539 | LLStatTime::LLStatTime(const std::string & key) | ||
540 | : LLStatAccum(false), | ||
541 | mFrameNumber(LLFrameTimer::getFrameCount()), | ||
542 | mTotalTimeInFrame(0), | ||
543 | mKey(key) | ||
544 | #if LL_DEBUG | ||
545 | , mRunning(FALSE) | ||
546 | #endif | ||
273 | { | 547 | { |
274 | } | 548 | } |
275 | 549 | ||
276 | void LLStatRate::count(U32 value) | 550 | void LLStatTime::start() |
551 | { | ||
552 | // Reset frame accumluation if the frame number has changed | ||
553 | U32 frame_number = LLFrameTimer::getFrameCount(); | ||
554 | if ( frame_number != mFrameNumber ) | ||
555 | { | ||
556 | mFrameNumber = frame_number; | ||
557 | mTotalTimeInFrame = 0; | ||
558 | } | ||
559 | |||
560 | sum(0.0); | ||
561 | |||
562 | #if LL_DEBUG | ||
563 | // Shouldn't be running already | ||
564 | llassert( !mRunning ); | ||
565 | mRunning = TRUE; | ||
566 | #endif | ||
567 | } | ||
568 | |||
569 | void LLStatTime::stop() | ||
570 | { | ||
571 | U64 end_time = getCurrentUsecs(); | ||
572 | U64 duration = end_time - mLastTime; | ||
573 | sum(F64(duration), end_time); | ||
574 | //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl; | ||
575 | mTotalTimeInFrame += duration; | ||
576 | |||
577 | #if LL_DEBUG | ||
578 | mRunning = FALSE; | ||
579 | #endif | ||
580 | } | ||
581 | |||
582 | /* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const | ||
277 | { | 583 | { |
278 | m.sum((F64)value * impl::sScaleTimes[SCALE_SECOND]); | 584 | if ( LLStatAccum::SCALE_PER_FRAME == scale ) |
585 | { | ||
586 | return mTotalTimeInFrame; | ||
587 | } | ||
588 | else | ||
589 | { | ||
590 | return LLStatAccum::meanValue(scale); | ||
591 | } | ||
279 | } | 592 | } |
280 | 593 | ||
281 | 594 | ||
282 | LLStatTime::LLStatTime(bool use_frame_timer) | 595 | // ------------------------------------------------------------------------ |
283 | : LLStatAccum(use_frame_timer) | 596 | |
597 | |||
598 | // Use this constructor for pre-defined LLStatTime objects | ||
599 | LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL) | ||
284 | { | 600 | { |
601 | if (mPredefinedStat) | ||
602 | { | ||
603 | // If dynamic stats are turned on, this will create a separate entry in the stat map. | ||
604 | initDynamicStat(mPredefinedStat->mKey); | ||
605 | |||
606 | // Start predefined stats. These stats are not part of the stat map. | ||
607 | mPredefinedStat->start(); | ||
608 | } | ||
285 | } | 609 | } |
286 | 610 | ||
287 | void LLStatTime::start() | 611 | // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key. |
612 | // These are also turned on or off via the switch passed in | ||
613 | LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL) | ||
288 | { | 614 | { |
289 | m.sum(0.0); | 615 | if (!sStatsEnabled) return; |
616 | |||
617 | if (NULL == key2 || strlen(key2) == 0) | ||
618 | { | ||
619 | initDynamicStat(key1); | ||
620 | } | ||
621 | else | ||
622 | { | ||
623 | std::ostringstream key; | ||
624 | key << key1 << "_" << key2; | ||
625 | initDynamicStat(key.str()); | ||
626 | } | ||
290 | } | 627 | } |
291 | 628 | ||
292 | void LLStatTime::stop() | 629 | void LLPerfBlock::initDynamicStat(const std::string& key) |
630 | { | ||
631 | // Early exit if dynamic stats aren't enabled. | ||
632 | if (!sStatsEnabled) return; | ||
633 | |||
634 | mLastPath = sCurrentStatPath; // Save and restore current path | ||
635 | sCurrentStatPath += "/" + key; // Add key to current path | ||
636 | |||
637 | // See if the LLStatTime object already exists | ||
638 | stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath); | ||
639 | if ( iter == sStatMap.end() ) | ||
640 | { | ||
641 | // StatEntry object doesn't exist, so create it | ||
642 | mDynamicStat = new StatEntry( key ); | ||
643 | sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path | ||
644 | } | ||
645 | else | ||
646 | { | ||
647 | // Found this path in the map, use the object there | ||
648 | mDynamicStat = (*iter).second; // Get StatEntry for the current path | ||
649 | } | ||
650 | |||
651 | if (mDynamicStat) | ||
652 | { | ||
653 | mDynamicStat->mStat.start(); | ||
654 | mDynamicStat->mCount++; | ||
655 | } | ||
656 | else | ||
657 | { | ||
658 | llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl; | ||
659 | sCurrentStatPath = mLastPath; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | |||
664 | // Destructor does the time accounting | ||
665 | LLPerfBlock::~LLPerfBlock() | ||
666 | { | ||
667 | if (mPredefinedStat) mPredefinedStat->stop(); | ||
668 | if (mDynamicStat) | ||
669 | { | ||
670 | mDynamicStat->mStat.stop(); | ||
671 | sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block | ||
672 | } | ||
673 | } | ||
674 | |||
675 | |||
676 | // Clear the map of any dynamic stats. Static routine | ||
677 | void LLPerfBlock::clearDynamicStats() | ||
678 | { | ||
679 | std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer()); | ||
680 | sStatMap.clear(); | ||
681 | } | ||
682 | |||
683 | // static - Extract the stat info into LLSD | ||
684 | void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, | ||
685 | LLStatAccum::TimeScale scale ) | ||
293 | { | 686 | { |
294 | U64 endTime = m.getCurrentUsecs(); | 687 | // If we aren't in per-frame scale, we need to go from second to microsecond. |
295 | m.sum((F64)(endTime - m.mLastTime), endTime); | 688 | U32 scale_adjustment = 1; |
689 | if (LLStatAccum::SCALE_PER_FRAME != scale) | ||
690 | { | ||
691 | scale_adjustment = USEC_PER_SEC; | ||
692 | } | ||
693 | stat_map_t::iterator iter = sStatMap.begin(); | ||
694 | for ( ; iter != sStatMap.end(); ++iter ) | ||
695 | { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time | ||
696 | const std::string & stats_full_path = (*iter).first; | ||
697 | |||
698 | StatEntry * stat = (*iter).second; | ||
699 | if (stat) | ||
700 | { | ||
701 | if (stat->mCount > 0) | ||
702 | { | ||
703 | stats[stats_full_path] = LLSD::emptyMap(); | ||
704 | stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale)); | ||
705 | if (stat->mCount > 1) | ||
706 | { | ||
707 | stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount; | ||
708 | } | ||
709 | stat->mCount = 0; | ||
710 | } | ||
711 | } | ||
712 | else | ||
713 | { // WTF? Shouldn't have a NULL pointer in the map. | ||
714 | llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl; | ||
715 | } | ||
716 | } | ||
296 | } | 717 | } |
297 | 718 | ||
298 | 719 | ||
720 | // ------------------------------------------------------------------------ | ||
299 | 721 | ||
300 | LLTimer LLStat::sTimer; | 722 | LLTimer LLStat::sTimer; |
301 | LLFrameTimer LLStat::sFrameTimer; | 723 | LLFrameTimer LLStat::sFrameTimer; |
diff --git a/linden/indra/llcommon/llstat.h b/linden/indra/llcommon/llstat.h index 0a7e014..63813e2 100644 --- a/linden/indra/llcommon/llstat.h +++ b/linden/indra/llcommon/llstat.h | |||
@@ -33,9 +33,13 @@ | |||
33 | #define LL_LLSTAT_H | 33 | #define LL_LLSTAT_H |
34 | 34 | ||
35 | #include <deque> | 35 | #include <deque> |
36 | #include <map> | ||
36 | 37 | ||
37 | #include "lltimer.h" | 38 | #include "lltimer.h" |
38 | #include "llframetimer.h" | 39 | #include "llframetimer.h" |
40 | #include "llfile.h" | ||
41 | |||
42 | class LLSD; | ||
39 | 43 | ||
40 | // Set this if longer stats are needed | 44 | // Set this if longer stats are needed |
41 | #define ENABLE_LONG_TIME_STATS 0 | 45 | #define ENABLE_LONG_TIME_STATS 0 |
@@ -58,25 +62,50 @@ public: | |||
58 | SCALE_100MS, | 62 | SCALE_100MS, |
59 | SCALE_SECOND, | 63 | SCALE_SECOND, |
60 | SCALE_MINUTE, | 64 | SCALE_MINUTE, |
61 | SCALE_TWO_MINUTE, | ||
62 | #if ENABLE_LONG_TIME_STATS | 65 | #if ENABLE_LONG_TIME_STATS |
63 | SCALE_HOUR, | 66 | SCALE_HOUR, |
64 | SCALE_DAY, | 67 | SCALE_DAY, |
65 | SCALE_WEEK, | 68 | SCALE_WEEK, |
66 | #endif | 69 | #endif |
67 | NUM_SCALES | 70 | NUM_SCALES, // Use to size storage arrays |
71 | SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets | ||
68 | }; | 72 | }; |
69 | 73 | ||
70 | F32 meanValue(TimeScale scale) const; | 74 | static U64 sScaleTimes[NUM_SCALES]; |
75 | |||
76 | virtual F32 meanValue(TimeScale scale) const; | ||
71 | // see the subclasses for the specific meaning of value | 77 | // see the subclasses for the specific meaning of value |
72 | 78 | ||
73 | F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); } | 79 | F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); } |
74 | F32 meanValueOverLastSecond() const { return meanValue(SCALE_SECOND); } | 80 | F32 meanValueOverLastSecond() const { return meanValue(SCALE_SECOND); } |
75 | F32 meanValueOverLastMinute() const { return meanValue(SCALE_MINUTE); } | 81 | F32 meanValueOverLastMinute() const { return meanValue(SCALE_MINUTE); } |
76 | 82 | ||
77 | protected: | 83 | void reset(U64 when); |
78 | class impl; | 84 | |
79 | impl& m; | 85 | void sum(F64 value); |
86 | void sum(F64 value, U64 when); | ||
87 | |||
88 | U64 getCurrentUsecs() const; | ||
89 | // Get current microseconds based on timer type | ||
90 | |||
91 | BOOL mUseFrameTimer; | ||
92 | BOOL mRunning; | ||
93 | |||
94 | U64 mLastTime; | ||
95 | |||
96 | struct Bucket | ||
97 | { | ||
98 | F64 accum; | ||
99 | U64 endTime; | ||
100 | |||
101 | BOOL lastValid; | ||
102 | F64 lastAccum; | ||
103 | }; | ||
104 | |||
105 | Bucket mBuckets[NUM_SCALES]; | ||
106 | |||
107 | BOOL mLastSampleValid; | ||
108 | F64 mLastSampleValue; | ||
80 | }; | 109 | }; |
81 | 110 | ||
82 | class LLStatMeasure : public LLStatAccum | 111 | class LLStatMeasure : public LLStatAccum |
@@ -105,39 +134,120 @@ public: | |||
105 | void count(U32); | 134 | void count(U32); |
106 | // used to note that n items have occured | 135 | // used to note that n items have occured |
107 | 136 | ||
108 | void mark() { count(1); } | 137 | void mark(); |
109 | // used for counting the rate thorugh a point in the code | 138 | // used for counting the rate thorugh a point in the code |
110 | }; | 139 | }; |
111 | 140 | ||
112 | 141 | ||
113 | class LLTimeBlock; | ||
114 | |||
115 | class LLStatTime : public LLStatAccum | 142 | class LLStatTime : public LLStatAccum |
116 | // gathers statistics about time spent in a block of code | 143 | // gathers statistics about time spent in a block of code |
117 | // measure average duration per second in the block | 144 | // measure average duration per second in the block |
118 | { | 145 | { |
119 | public: | 146 | public: |
120 | LLStatTime(bool use_frame_timer = false); | 147 | LLStatTime( const std::string & key = "undefined" ); |
148 | |||
149 | U32 mFrameNumber; // Current frame number | ||
150 | U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame | ||
151 | |||
152 | void setKey( const std::string & key ) { mKey = key; }; | ||
153 | |||
154 | virtual F32 meanValue(TimeScale scale) const; | ||
121 | 155 | ||
122 | private: | 156 | private: |
123 | void start(); | 157 | void start(); // Start and stop measuring time block |
124 | void stop(); | 158 | void stop(); |
125 | friend class LLTimeBlock; | 159 | |
160 | std::string mKey; // Tag representing this time block | ||
161 | |||
162 | #if LL_DEBUG | ||
163 | BOOL mRunning; // TRUE if start() has been called | ||
164 | #endif | ||
165 | |||
166 | friend class LLPerfBlock; | ||
126 | }; | 167 | }; |
127 | 168 | ||
128 | class LLTimeBlock | 169 | // ---------------------------------------------------------------------------- |
170 | |||
171 | |||
172 | // Use this class on the stack to record statistics about an area of code | ||
173 | class LLPerfBlock | ||
129 | { | 174 | { |
130 | public: | 175 | public: |
131 | LLTimeBlock(LLStatTime& stat) : mStat(stat) { mStat.start(); } | 176 | struct StatEntry |
132 | ~LLTimeBlock() { mStat.stop(); } | 177 | { |
178 | StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {} | ||
179 | LLStatTime mStat; | ||
180 | U32 mCount; | ||
181 | }; | ||
182 | typedef std::map<std::string, StatEntry*> stat_map_t; | ||
183 | |||
184 | // Use this constructor for pre-defined LLStatTime objects | ||
185 | LLPerfBlock(LLStatTime* stat); | ||
186 | |||
187 | // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key | ||
188 | LLPerfBlock( const char* key1, const char* key2 = NULL); | ||
189 | |||
190 | |||
191 | ~LLPerfBlock(); | ||
192 | |||
193 | static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; }; | ||
194 | static S32 getStatsEnabled() { return sStatsEnabled; }; | ||
195 | |||
196 | static void clearDynamicStats(); // Reset maps to clear out dynamic objects | ||
197 | static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin | ||
198 | LLStatAccum::TimeScale scale ); | ||
199 | |||
133 | private: | 200 | private: |
134 | LLStatTime& mStat; | 201 | // Initialize dynamically created LLStatTime objects |
202 | void initDynamicStat(const std::string& key); | ||
203 | |||
204 | std::string mLastPath; // Save sCurrentStatPath when this is called | ||
205 | LLStatTime * mPredefinedStat; // LLStatTime object to get data | ||
206 | StatEntry * mDynamicStat; // StatEntryobject to get data | ||
207 | |||
208 | static BOOL sStatsEnabled; // Normally FALSE | ||
209 | static stat_map_t sStatMap; // Map full path string to LLStatTime objects | ||
210 | static std::string sCurrentStatPath; // Something like "frame/physics/physics step" | ||
135 | }; | 211 | }; |
136 | 212 | ||
213 | // ---------------------------------------------------------------------------- | ||
137 | 214 | ||
215 | class LLPerfStats | ||
216 | { | ||
217 | public: | ||
218 | LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0); | ||
219 | virtual ~LLPerfStats(); | ||
220 | |||
221 | virtual void init(); // Reset and start all stat timers | ||
222 | virtual void updatePerFrameStats(); | ||
223 | // Override these function to add process-specific information to the performance log header and per-frame logging. | ||
224 | virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ } | ||
225 | virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ } | ||
226 | |||
227 | // High-resolution frame stats | ||
228 | BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); }; | ||
229 | F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; }; | ||
230 | void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; }; | ||
231 | void setReportPerformanceDuration( F32 seconds ); | ||
232 | void setProcessName(const std::string& process_name) { mProcessName = process_name; } | ||
233 | void setProcessPID(S32 process_pid) { mProcessPID = process_pid; } | ||
138 | 234 | ||
235 | protected: | ||
236 | void openPerfStatsFile(); // Open file for high resolution metrics logging | ||
237 | void dumpIntervalPerformanceStats(); | ||
238 | |||
239 | llofstream mFrameStatsFile; // File for per-frame stats | ||
240 | BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts | ||
241 | BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report | ||
242 | std::string mProcessName; | ||
243 | S32 mProcessPID; | ||
139 | 244 | ||
245 | private: | ||
246 | F32 mReportPerformanceStatInterval; // Seconds between performance stats | ||
247 | F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats | ||
248 | }; | ||
140 | 249 | ||
250 | // ---------------------------------------------------------------------------- | ||
141 | class LLStat | 251 | class LLStat |
142 | { | 252 | { |
143 | public: | 253 | public: |
diff --git a/linden/indra/llcommon/llstatenums.h b/linden/indra/llcommon/llstatenums.h index 6866586..1d9b863 100644 --- a/linden/indra/llcommon/llstatenums.h +++ b/linden/indra/llcommon/llstatenums.h | |||
@@ -33,38 +33,41 @@ | |||
33 | 33 | ||
34 | enum | 34 | enum |
35 | { | 35 | { |
36 | LL_SIM_STAT_TIME_DILATION, | 36 | LL_SIM_STAT_TIME_DILATION, // 0 |
37 | LL_SIM_STAT_FPS, | 37 | LL_SIM_STAT_FPS, |
38 | LL_SIM_STAT_PHYSFPS, | 38 | LL_SIM_STAT_PHYSFPS, |
39 | LL_SIM_STAT_AGENTUPS, | 39 | LL_SIM_STAT_AGENTUPS, |
40 | LL_SIM_STAT_FRAMEMS, | 40 | LL_SIM_STAT_FRAMEMS, |
41 | LL_SIM_STAT_NETMS, | 41 | LL_SIM_STAT_NETMS, // 5 |
42 | LL_SIM_STAT_SIMOTHERMS, | 42 | LL_SIM_STAT_SIMOTHERMS, |
43 | LL_SIM_STAT_SIMPHYSICSMS, | 43 | LL_SIM_STAT_SIMPHYSICSMS, |
44 | LL_SIM_STAT_AGENTMS, | 44 | LL_SIM_STAT_AGENTMS, |
45 | LL_SIM_STAT_IMAGESMS, | 45 | LL_SIM_STAT_IMAGESMS, |
46 | LL_SIM_STAT_SCRIPTMS, | 46 | LL_SIM_STAT_SCRIPTMS, // 10 |
47 | LL_SIM_STAT_NUMTASKS, | 47 | LL_SIM_STAT_NUMTASKS, |
48 | LL_SIM_STAT_NUMTASKSACTIVE, | 48 | LL_SIM_STAT_NUMTASKSACTIVE, |
49 | LL_SIM_STAT_NUMAGENTMAIN, | 49 | LL_SIM_STAT_NUMAGENTMAIN, |
50 | LL_SIM_STAT_NUMAGENTCHILD, | 50 | LL_SIM_STAT_NUMAGENTCHILD, |
51 | LL_SIM_STAT_NUMSCRIPTSACTIVE, | 51 | LL_SIM_STAT_NUMSCRIPTSACTIVE, // 15 |
52 | LL_SIM_STAT_LSLIPS, | 52 | LL_SIM_STAT_LSLIPS, |
53 | LL_SIM_STAT_INPPS, | 53 | LL_SIM_STAT_INPPS, |
54 | LL_SIM_STAT_OUTPPS, | 54 | LL_SIM_STAT_OUTPPS, |
55 | LL_SIM_STAT_PENDING_DOWNLOADS, | 55 | LL_SIM_STAT_PENDING_DOWNLOADS, |
56 | LL_SIM_STAT_PENDING_UPLOADS, | 56 | LL_SIM_STAT_PENDING_UPLOADS, // 20 |
57 | LL_SIM_STAT_VIRTUAL_SIZE_KB, | 57 | LL_SIM_STAT_VIRTUAL_SIZE_KB, |
58 | LL_SIM_STAT_RESIDENT_SIZE_KB, | 58 | LL_SIM_STAT_RESIDENT_SIZE_KB, |
59 | LL_SIM_STAT_PENDING_LOCAL_UPLOADS, | 59 | LL_SIM_STAT_PENDING_LOCAL_UPLOADS, |
60 | LL_SIM_STAT_TOTAL_UNACKED_BYTES, | 60 | LL_SIM_STAT_TOTAL_UNACKED_BYTES, |
61 | LL_SIM_STAT_PHYSICS_PINNED_TASKS, | 61 | LL_SIM_STAT_PHYSICS_PINNED_TASKS, // 25 |
62 | LL_SIM_STAT_PHYSICS_LOD_TASKS, | 62 | LL_SIM_STAT_PHYSICS_LOD_TASKS, |
63 | LL_SIM_STAT_SIMPHYSICSSTEPMS, | 63 | LL_SIM_STAT_SIMPHYSICSSTEPMS, |
64 | LL_SIM_STAT_SIMPHYSICSSHAPEMS, | 64 | LL_SIM_STAT_SIMPHYSICSSHAPEMS, |
65 | LL_SIM_STAT_SIMPHYSICSOTHERMS, | 65 | LL_SIM_STAT_SIMPHYSICSOTHERMS, |
66 | LL_SIM_STAT_SIMPHYSICSMEMORY, | 66 | LL_SIM_STAT_SIMPHYSICSMEMORY, // 30 |
67 | LL_SIM_STAT_SCRIPT_EPS, | 67 | LL_SIM_STAT_SCRIPT_EPS, |
68 | LL_SIM_STAT_SIMSPARETIME, | ||
69 | LL_SIM_STAT_SIMSLEEPTIME, | ||
70 | LL_SIM_STAT_IOPUMPTIME, | ||
68 | }; | 71 | }; |
69 | 72 | ||
70 | #endif | 73 | #endif |
diff --git a/linden/indra/llcommon/llstl.h b/linden/indra/llcommon/llstl.h index 4486727..70a2cc0 100644 --- a/linden/indra/llcommon/llstl.h +++ b/linden/indra/llcommon/llstl.h | |||
@@ -79,6 +79,9 @@ struct compare_pointer_contents | |||
79 | // The general form is: | 79 | // The general form is: |
80 | // | 80 | // |
81 | // std::for_each(cont.begin(), cont.end(), DeletePointer()); | 81 | // std::for_each(cont.begin(), cont.end(), DeletePointer()); |
82 | // somemap.clear(); | ||
83 | // | ||
84 | // Don't forget to clear()! | ||
82 | 85 | ||
83 | struct DeletePointer | 86 | struct DeletePointer |
84 | { | 87 | { |
@@ -95,7 +98,7 @@ struct DeletePointerArray | |||
95 | } | 98 | } |
96 | }; | 99 | }; |
97 | 100 | ||
98 | // DeletePointer is a simple helper for deleting all pointers in a map. | 101 | // DeletePairedPointer is a simple helper for deleting all pointers in a map. |
99 | // The general form is: | 102 | // The general form is: |
100 | // | 103 | // |
101 | // std::for_each(somemap.begin(), somemap.end(), DeletePairedPointer()); | 104 | // std::for_each(somemap.begin(), somemap.end(), DeletePairedPointer()); |
diff --git a/linden/indra/llcommon/llstring.h b/linden/indra/llcommon/llstring.h index 7b08fd3..5e75188 100644 --- a/linden/indra/llcommon/llstring.h +++ b/linden/indra/llcommon/llstring.h | |||
@@ -133,26 +133,32 @@ struct char_traits<U16> | |||
133 | class LLStringOps | 133 | class LLStringOps |
134 | { | 134 | { |
135 | public: | 135 | public: |
136 | static char toUpper(char elem) { return toupper(elem); } | 136 | static char toUpper(char elem) { return toupper((unsigned char)elem); } |
137 | static llwchar toUpper(llwchar elem) { return towupper(elem); } | 137 | static llwchar toUpper(llwchar elem) { return towupper(elem); } |
138 | 138 | ||
139 | static char toLower(char elem) { return tolower(elem); } | 139 | static char toLower(char elem) { return tolower((unsigned char)elem); } |
140 | static llwchar toLower(llwchar elem) { return towlower(elem); } | 140 | static llwchar toLower(llwchar elem) { return towlower(elem); } |
141 | 141 | ||
142 | static BOOL isSpace(char elem) { return isspace(elem) != 0; } | 142 | static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; } |
143 | static BOOL isSpace(llwchar elem) { return iswspace(elem) != 0; } | 143 | static bool isSpace(llwchar elem) { return iswspace(elem) != 0; } |
144 | 144 | ||
145 | static BOOL isUpper(char elem) { return isupper(elem) != 0; } | 145 | static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; } |
146 | static BOOL isUpper(llwchar elem) { return iswupper(elem) != 0; } | 146 | static bool isUpper(llwchar elem) { return iswupper(elem) != 0; } |
147 | 147 | ||
148 | static BOOL isLower(char elem) { return islower(elem) != 0; } | 148 | static bool isLower(char elem) { return islower((unsigned char)elem) != 0; } |
149 | static BOOL isLower(llwchar elem) { return iswlower(elem) != 0; } | 149 | static bool isLower(llwchar elem) { return iswlower(elem) != 0; } |
150 | |||
151 | static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; } | ||
152 | static bool isDigit(llwchar a) { return iswdigit(a) != 0; } | ||
153 | |||
154 | static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } | ||
155 | static bool isPunct(llwchar a) { return iswpunct(a) != 0; } | ||
156 | |||
157 | static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } | ||
158 | static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } | ||
150 | 159 | ||
151 | static S32 collate(const char* a, const char* b) { return strcoll(a, b); } | 160 | static S32 collate(const char* a, const char* b) { return strcoll(a, b); } |
152 | static S32 collate(const llwchar* a, const llwchar* b); | 161 | static S32 collate(const llwchar* a, const llwchar* b); |
153 | |||
154 | static BOOL isDigit(char a) { return isdigit(a) != 0; } | ||
155 | static BOOL isDigit(llwchar a) { return iswdigit(a) != 0; } | ||
156 | }; | 162 | }; |
157 | 163 | ||
158 | /** | 164 | /** |
@@ -194,7 +200,7 @@ public: | |||
194 | typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; | 200 | typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; |
195 | static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map); | 201 | static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map); |
196 | 202 | ||
197 | static BOOL isValidIndex(const std::basic_string<T>& string, size_type i) | 203 | static bool isValidIndex(const std::basic_string<T>& string, size_type i) |
198 | { | 204 | { |
199 | return !string.empty() && (0 <= i) && (i <= string.size()); | 205 | return !string.empty() && (0 <= i) && (i <= string.size()); |
200 | } | 206 | } |
@@ -1155,13 +1161,6 @@ BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& | |||
1155 | std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); | 1161 | std::basic_istringstream<T> i_stream((std::basic_string<T>)temp); |
1156 | if(i_stream >> v) | 1162 | if(i_stream >> v) |
1157 | { | 1163 | { |
1158 | //TODO: figure out overflow reporting here | ||
1159 | //if( ULONG_MAX == v ) | ||
1160 | //{ | ||
1161 | // // Underflow or overflow | ||
1162 | // return FALSE; | ||
1163 | //} | ||
1164 | |||
1165 | value = v; | 1164 | value = v; |
1166 | return TRUE; | 1165 | return TRUE; |
1167 | } | 1166 | } |
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp index 822adc2..8bc9aac 100644 --- a/linden/indra/llcommon/llthread.cpp +++ b/linden/indra/llcommon/llthread.cpp | |||
@@ -359,7 +359,7 @@ void LLCondition::broadcast() | |||
359 | LLMutex* LLThreadSafeRefCount::sMutex = 0; | 359 | LLMutex* LLThreadSafeRefCount::sMutex = 0; |
360 | 360 | ||
361 | //static | 361 | //static |
362 | void LLThreadSafeRefCount::initClass() | 362 | void LLThreadSafeRefCount::initThreadSafeRefCount() |
363 | { | 363 | { |
364 | if (!sMutex) | 364 | if (!sMutex) |
365 | { | 365 | { |
@@ -368,7 +368,7 @@ void LLThreadSafeRefCount::initClass() | |||
368 | } | 368 | } |
369 | 369 | ||
370 | //static | 370 | //static |
371 | void LLThreadSafeRefCount::cleanupClass() | 371 | void LLThreadSafeRefCount::cleanupThreadSafeRefCount() |
372 | { | 372 | { |
373 | delete sMutex; | 373 | delete sMutex; |
374 | sMutex = NULL; | 374 | sMutex = NULL; |
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h index 9da3134..923de56 100644 --- a/linden/indra/llcommon/llthread.h +++ b/linden/indra/llcommon/llthread.h | |||
@@ -191,8 +191,8 @@ void LLThread::unlockData() | |||
191 | class LLThreadSafeRefCount | 191 | class LLThreadSafeRefCount |
192 | { | 192 | { |
193 | public: | 193 | public: |
194 | static void initClass(); // creates sMutex | 194 | static void initThreadSafeRefCount(); // creates sMutex |
195 | static void cleanupClass(); // destroys sMutex | 195 | static void cleanupThreadSafeRefCount(); // destroys sMutex |
196 | 196 | ||
197 | private: | 197 | private: |
198 | static LLMutex* sMutex; | 198 | static LLMutex* sMutex; |
diff --git a/linden/indra/llcommon/lltimer.cpp b/linden/indra/llcommon/lltimer.cpp index 967570d..47edfd0 100644 --- a/linden/indra/llcommon/lltimer.cpp +++ b/linden/indra/llcommon/lltimer.cpp | |||
@@ -83,15 +83,20 @@ void ms_sleep(U32 ms) | |||
83 | { | 83 | { |
84 | Sleep(ms); | 84 | Sleep(ms); |
85 | } | 85 | } |
86 | |||
87 | U32 micro_sleep(U64 us, U32 max_yields) | ||
88 | { | ||
89 | // max_yields is unused; just fiddle with it to avoid warnings. | ||
90 | max_yields = 0; | ||
91 | ms_sleep(us / 1000); | ||
92 | return 0; | ||
93 | } | ||
86 | #elif LL_LINUX || LL_SOLARIS || LL_DARWIN | 94 | #elif LL_LINUX || LL_SOLARIS || LL_DARWIN |
87 | void ms_sleep(U32 ms) | 95 | static void _sleep_loop(struct timespec& thiswait) |
88 | { | 96 | { |
89 | long mslong = ms; // tv_nsec is a long | 97 | struct timespec nextwait; |
90 | struct timespec thiswait, nextwait; | ||
91 | bool sleep_more = false; | 98 | bool sleep_more = false; |
92 | 99 | ||
93 | thiswait.tv_sec = ms / 1000; | ||
94 | thiswait.tv_nsec = (mslong % 1000) * 1000000l; | ||
95 | do { | 100 | do { |
96 | int result = nanosleep(&thiswait, &nextwait); | 101 | int result = nanosleep(&thiswait, &nextwait); |
97 | 102 | ||
@@ -127,6 +132,44 @@ void ms_sleep(U32 ms) | |||
127 | } | 132 | } |
128 | } while (sleep_more); | 133 | } while (sleep_more); |
129 | } | 134 | } |
135 | |||
136 | U32 micro_sleep(U64 us, U32 max_yields) | ||
137 | { | ||
138 | U64 start = get_clock_count(); | ||
139 | // This is kernel dependent. Currently, our kernel generates software clock | ||
140 | // interrupts at 250 Hz (every 4,000 microseconds). | ||
141 | const U64 KERNEL_SLEEP_INTERVAL_US = 4000; | ||
142 | |||
143 | S32 num_sleep_intervals = (us - (KERNEL_SLEEP_INTERVAL_US >> 1)) / KERNEL_SLEEP_INTERVAL_US; | ||
144 | if (num_sleep_intervals > 0) | ||
145 | { | ||
146 | U64 sleep_time = (num_sleep_intervals * KERNEL_SLEEP_INTERVAL_US) - (KERNEL_SLEEP_INTERVAL_US >> 1); | ||
147 | struct timespec thiswait; | ||
148 | thiswait.tv_sec = sleep_time / 1000000; | ||
149 | thiswait.tv_nsec = (sleep_time % 1000000) * 1000l; | ||
150 | _sleep_loop(thiswait); | ||
151 | } | ||
152 | |||
153 | U64 current_clock = get_clock_count(); | ||
154 | U32 yields = 0; | ||
155 | while ( (yields < max_yields) | ||
156 | && (current_clock - start < us) ) | ||
157 | { | ||
158 | sched_yield(); | ||
159 | ++yields; | ||
160 | current_clock = get_clock_count(); | ||
161 | } | ||
162 | return yields; | ||
163 | } | ||
164 | |||
165 | void ms_sleep(U32 ms) | ||
166 | { | ||
167 | long mslong = ms; // tv_nsec is a long | ||
168 | struct timespec thiswait; | ||
169 | thiswait.tv_sec = ms / 1000; | ||
170 | thiswait.tv_nsec = (mslong % 1000) * 1000000l; | ||
171 | _sleep_loop(thiswait); | ||
172 | } | ||
130 | #else | 173 | #else |
131 | # error "architecture not supported" | 174 | # error "architecture not supported" |
132 | #endif | 175 | #endif |
diff --git a/linden/indra/llcommon/lltimer.h b/linden/indra/llcommon/lltimer.h index 8d94276..766645b 100644 --- a/linden/indra/llcommon/lltimer.h +++ b/linden/indra/llcommon/lltimer.h | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | #include "stdtypes.h" | 40 | #include "stdtypes.h" |
41 | 41 | ||
42 | #include <string> | ||
43 | #include <list> | ||
42 | // units conversions | 44 | // units conversions |
43 | #ifndef USEC_PER_SEC | 45 | #ifndef USEC_PER_SEC |
44 | const U32 USEC_PER_SEC = 1000000; | 46 | const U32 USEC_PER_SEC = 1000000; |
@@ -115,6 +117,7 @@ void update_clock_frequencies(); | |||
115 | 117 | ||
116 | // Sleep for milliseconds | 118 | // Sleep for milliseconds |
117 | void ms_sleep(U32 ms); | 119 | void ms_sleep(U32 ms); |
120 | U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF); | ||
118 | 121 | ||
119 | // Returns the correct UTC time in seconds, like time(NULL). | 122 | // Returns the correct UTC time in seconds, like time(NULL). |
120 | // Useful on the viewer, which may have its local clock set wrong. | 123 | // Useful on the viewer, which may have its local clock set wrong. |
@@ -184,7 +187,7 @@ protected: | |||
184 | 187 | ||
185 | private: | 188 | private: |
186 | //list of active timers | 189 | //list of active timers |
187 | static std::list<LLEventTimer*> sActiveList; | 190 | static std::list<LLEventTimer*> sActiveList; // TODO should this be a vector |
188 | }; | 191 | }; |
189 | 192 | ||
190 | #endif | 193 | #endif |
diff --git a/linden/indra/llcommon/llversionserver.h b/linden/indra/llcommon/llversionserver.h index 0b88ce8..2861428 100644 --- a/linden/indra/llcommon/llversionserver.h +++ b/linden/indra/llcommon/llversionserver.h | |||
@@ -34,8 +34,8 @@ | |||
34 | 34 | ||
35 | const S32 LL_VERSION_MAJOR = 1; | 35 | const S32 LL_VERSION_MAJOR = 1; |
36 | const S32 LL_VERSION_MINOR = 24; | 36 | const S32 LL_VERSION_MINOR = 24; |
37 | const S32 LL_VERSION_PATCH = 0; | 37 | const S32 LL_VERSION_PATCH = 9; |
38 | const S32 LL_VERSION_BUILD = 93453; | 38 | const S32 LL_VERSION_BUILD = 98650; |
39 | 39 | ||
40 | const char * const LL_CHANNEL = "Second Life Server"; | 40 | const char * const LL_CHANNEL = "Second Life Server"; |
41 | 41 | ||
diff --git a/linden/indra/llcommon/llversionviewer.h b/linden/indra/llcommon/llversionviewer.h index 66462b3..6e7d6ce 100644 --- a/linden/indra/llcommon/llversionviewer.h +++ b/linden/indra/llcommon/llversionviewer.h | |||
@@ -33,8 +33,8 @@ | |||
33 | #define LL_LLVERSIONVIEWER_H | 33 | #define LL_LLVERSIONVIEWER_H |
34 | 34 | ||
35 | const S32 LL_VERSION_MAJOR = 1; | 35 | const S32 LL_VERSION_MAJOR = 1; |
36 | const S32 LL_VERSION_MINOR = 21; | 36 | const S32 LL_VERSION_MINOR = 22; |
37 | const S32 LL_VERSION_PATCH = 6; | 37 | const S32 LL_VERSION_PATCH = 0; |
38 | const S32 LL_VERSION_BUILD = 0; | 38 | const S32 LL_VERSION_BUILD = 0; |
39 | 39 | ||
40 | const char * const LL_CHANNEL = "Second Life Release"; | 40 | const char * const LL_CHANNEL = "Second Life Release"; |