Skip to content
Snippets Groups Projects
Commit 9faaa28f authored by Richard Linden's avatar Richard Linden
Browse files

SH-4346 FIX Interesting: some integer Statistics are displayed as floating...

SH-4346 FIX Interesting: some integer Statistics are displayed as floating point after crossing region boundary
fine-tuned heuristics for switching between mean and current values in stat bar display
added comments to LLUnits unit test
parent b39cf477
Branches
Tags
No related merge requests found
...@@ -53,30 +53,29 @@ namespace tut ...@@ -53,30 +53,29 @@ namespace tut
template<> template<> template<> template<>
void units_object_t::test<1>() void units_object_t::test<1>()
{ {
LL_INFOS("test") << "Test" << LL_ENDL;
LLUnit<F32, Quatloos> float_quatloos; LLUnit<F32, Quatloos> float_quatloos;
ensure(float_quatloos == 0.f); ensure("default float unit is zero", float_quatloos == 0.f);
LLUnit<F32, Quatloos> float_initialize_quatloos(1); LLUnit<F32, Quatloos> float_initialize_quatloos(1);
ensure(float_initialize_quatloos == 1.f); ensure("non-zero initialized unit", float_initialize_quatloos == 1.f);
LLUnit<S32, Quatloos> int_quatloos; LLUnit<S32, Quatloos> int_quatloos;
ensure(int_quatloos == 0); ensure("default int unit is zero", int_quatloos == 0);
int_quatloos = 42; int_quatloos = 42;
ensure(int_quatloos == 42); ensure("int assignment is preserved", int_quatloos == 42);
float_quatloos = int_quatloos; float_quatloos = int_quatloos;
ensure(float_quatloos == 42.f); ensure("float assignment from int preserves value", float_quatloos == 42.f);
int_quatloos = float_quatloos; int_quatloos = float_quatloos;
ensure(int_quatloos == 42); ensure("int assignment from float preserves value", int_quatloos == 42);
float_quatloos = 42.1f; float_quatloos = 42.1f;
ensure(float_quatloos == 42.1f);
int_quatloos = float_quatloos; int_quatloos = float_quatloos;
ensure(int_quatloos == 42); ensure("int units truncate float units on assignment", int_quatloos == 42);
LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos); LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
ensure(unsigned_int_quatloos == 42); ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == 42);
} }
// conversions to/from base unit // conversions to/from base unit
...@@ -84,36 +83,35 @@ namespace tut ...@@ -84,36 +83,35 @@ namespace tut
void units_object_t::test<2>() void units_object_t::test<2>()
{ {
LLUnit<F32, Quatloos> quatloos(1.f); LLUnit<F32, Quatloos> quatloos(1.f);
ensure(quatloos == 1.f);
LLUnit<F32, Latinum> latinum_bars(quatloos); LLUnit<F32, Latinum> latinum_bars(quatloos);
ensure(latinum_bars == 1.f / 4.f); ensure("conversion between units is automatic via initialization", latinum_bars == 1.f / 4.f);
latinum_bars = 256; latinum_bars = 256;
quatloos = latinum_bars; quatloos = latinum_bars;
ensure(quatloos == 1024); ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == 1024);
LLUnit<F32, Solari> solari(quatloos);
ensure(solari == 4096);
// division of integral unit
LLUnit<S32, Quatloos> single_quatloo(1); LLUnit<S32, Quatloos> single_quatloo(1);
LLUnit<F32, Latinum> quarter_latinum = single_quatloo; LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
ensure(quarter_latinum == 0.25f); ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == 0.25f);
} }
// conversions across non-base units // conversions across non-base units
template<> template<> template<> template<>
void units_object_t::test<3>() void units_object_t::test<3>()
{ {
LLUnit<F32, Solari> solari = 4.f; LLUnit<F32, Quatloos> quatloos(1024);
LLUnit<F32, Solari> solari(quatloos);
ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == 4096);
LLUnit<F32, Latinum> latinum_bars = solari; LLUnit<F32, Latinum> latinum_bars = solari;
ensure(latinum_bars == 0.25f); ensure("Non base units can be converted between each other", latinum_bars == 256);
} }
// math operations // math operations
template<> template<> template<> template<>
void units_object_t::test<4>() void units_object_t::test<4>()
{ {
// exercise math operations
LLUnit<F32, Quatloos> quatloos = 1.f; LLUnit<F32, Quatloos> quatloos = 1.f;
quatloos *= 4.f; quatloos *= 4.f;
ensure(quatloos == 4); ensure(quatloos == 4);
...@@ -142,44 +140,34 @@ namespace tut ...@@ -142,44 +140,34 @@ namespace tut
quatloos -= 4.f; quatloos -= 4.f;
ensure(quatloos == 16); ensure(quatloos == 16);
quatloos *= 2.f;
ensure(quatloos == 32);
quatloos = quatloos * 2.f;
ensure(quatloos == 64);
quatloos = 0.5f * quatloos;
ensure(quatloos == 32);
quatloos /= 2.f; quatloos /= 2.f;
ensure(quatloos == 16); ensure(quatloos == 8);
quatloos = quatloos / 4; quatloos = quatloos / 4;
ensure(quatloos == 4); ensure(quatloos == 2);
F32 ratio = quatloos / LLUnit<F32, Quatloos>(4.f); F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
ensure(ratio == 1); ensure(ratio == 1);
ratio = quatloos / LLUnit<F32, Solari>(16.f); ratio = quatloos / LLUnit<F32, Solari>(8.f);
ensure(ratio == 1); ensure(ratio == 1);
quatloos += LLUnit<F32, Solari>(4.f); quatloos += LLUnit<F32, Solari>(8.f);
ensure(quatloos == 5); ensure(quatloos == 4);
quatloos -= LLUnit<F32, Latinum>(1.f); quatloos -= LLUnit<F32, Latinum>(1.f);
ensure(quatloos == 1); ensure(quatloos == 0);
} }
// implicit units // implicit units
template<> template<> template<> template<>
void units_object_t::test<5>() void units_object_t::test<5>()
{ {
// 0-initialized
LLUnit<F32, Quatloos> quatloos; LLUnit<F32, Quatloos> quatloos;
// initialize implicit unit from explicit
LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1; LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1;
ensure(quatloos_implicit == 1); ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
// assign implicit to explicit, or perform math operations
quatloos = quatloos_implicit; quatloos = quatloos_implicit;
ensure(quatloos == 1); ensure("can assign implicit unit to explicit unit", quatloos == 1);
quatloos += quatloos_implicit; quatloos += quatloos_implicit;
ensure(quatloos == 2); ensure("can perform math operation using mixture of implicit and explicit units", quatloos == 2);
// math operations on implicits // math operations on implicits
quatloos_implicit = 1; quatloos_implicit = 1;
...@@ -211,15 +199,13 @@ namespace tut ...@@ -211,15 +199,13 @@ namespace tut
// implicit conversion to POD // implicit conversion to POD
F32 float_val = quatloos_implicit; F32 float_val = quatloos_implicit;
ensure(float_val == 16); ensure("implicit units convert implicitly to regular values", float_val == 16);
S32 int_val = quatloos_implicit; S32 int_val = quatloos_implicit;
ensure(int_val == 16); ensure("implicit units convert implicitly to regular values", int_val == 16);
// conversion of implicits // conversion of implicits
LLUnitImplicit<F32, Latinum> latinum_implicit(2); LLUnitImplicit<F32, Latinum> latinum_implicit(2);
ensure(latinum_implicit == 2); ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
ensure(latinum_implicit * 2 == quatloos_implicit);
} }
} }
...@@ -41,6 +41,16 @@ ...@@ -41,6 +41,16 @@
#include "lllocalcliprect.h" #include "lllocalcliprect.h"
#include <iostream> #include <iostream>
// rate at which to update display of value that is rapidly changing
const F32 MEAN_VALUE_UPDATE_TIME = 1.f / 4.f;
// time between value changes that qualifies as a "rapid change"
const LLUnit<F32, LLUnits::Seconds> RAPID_CHANGE_THRESHOLD = 0.2f;
// maximum number of rapid changes in RAPID_CHANGE_WINDOW before switching over to displaying the mean
// instead of latest value
const S32 MAX_RAPID_CHANGES_PER_SEC = 10;
// period of time over which to measure rapid changes
const LLUnit<F32, LLUnits::Seconds> RAPID_CHANGE_WINDOW = 1.f;
F32 calc_tick_value(F32 min, F32 max) F32 calc_tick_value(F32 min, F32 max)
{ {
F32 range = max - min; F32 range = max - min;
...@@ -141,6 +151,25 @@ void calc_auto_scale_range(F32& min, F32& max, F32& tick) ...@@ -141,6 +151,25 @@ void calc_auto_scale_range(F32& min, F32& max, F32& tick)
max = out_max; max = out_max;
} }
LLStatBar::Params::Params()
: label("label"),
unit_label("unit_label"),
bar_min("bar_min", 0.f),
bar_max("bar_max", 0.f),
tick_spacing("tick_spacing", 0.f),
decimal_digits("decimal_digits", 3),
show_bar("show_bar", false),
show_history("show_history", false),
scale_range("scale_range", true),
num_frames("num_frames", 200),
num_frames_short("num_frames_short", 20),
max_height("max_height", 100),
stat("stat"),
orientation("orientation", VERTICAL)
{
changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT);
}
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
LLStatBar::LLStatBar(const Params& p) LLStatBar::LLStatBar(const Params& p)
...@@ -253,7 +282,6 @@ S32 calc_num_rapid_changes(LLTrace::PeriodicRecording& periodic_recording, const ...@@ -253,7 +282,6 @@ S32 calc_num_rapid_changes(LLTrace::PeriodicRecording& periodic_recording, const
LLUnit<F32, LLUnits::Seconds> elapsed_time, LLUnit<F32, LLUnits::Seconds> elapsed_time,
time_since_value_changed; time_since_value_changed;
S32 num_rapid_changes = 0; S32 num_rapid_changes = 0;
const LLUnit<F32, LLUnits::Seconds> RAPID_CHANGE_THRESHOLD = LLUnits::Seconds::fromValue(0.3f);
F64 last_value = periodic_recording.getPrevRecording(1).getSum(stat); F64 last_value = periodic_recording.getPrevRecording(1).getSum(stat);
for (S32 i = 1; i < periodic_recording.getNumRecordedPeriods(); i++) for (S32 i = 1; i < periodic_recording.getNumRecordedPeriods(); i++)
...@@ -293,10 +321,6 @@ void LLStatBar::draw() ...@@ -293,10 +321,6 @@ void LLStatBar::draw()
: mNumShortHistoryFrames; : mNumShortHistoryFrames;
S32 num_rapid_changes = 0; S32 num_rapid_changes = 0;
const S32 MAX_RAPID_CHANGES = 6;
const F32 MIN_VALUE_UPDATE_TIME = 1.f / 4.f;
const LLUnit<F32, LLUnits::Seconds> CHANGE_WINDOW = LLUnits::Seconds::fromValue(2.f);
if (mCountFloatp) if (mCountFloatp)
{ {
const LLTrace::TraceType<LLTrace::CountAccumulator>& count_stat = *mCountFloatp; const LLTrace::TraceType<LLTrace::CountAccumulator>& count_stat = *mCountFloatp;
...@@ -306,44 +330,41 @@ void LLStatBar::draw() ...@@ -306,44 +330,41 @@ void LLStatBar::draw()
min = frame_recording.getPeriodMinPerSec(count_stat, num_frames); min = frame_recording.getPeriodMinPerSec(count_stat, num_frames);
max = frame_recording.getPeriodMaxPerSec(count_stat, num_frames); max = frame_recording.getPeriodMaxPerSec(count_stat, num_frames);
mean = frame_recording.getPeriodMeanPerSec(count_stat, num_frames); mean = frame_recording.getPeriodMeanPerSec(count_stat, num_frames);
num_rapid_changes = calc_num_rapid_changes(frame_recording, count_stat, CHANGE_WINDOW); display_value = mean;
} }
else if (mEventFloatp) else if (mEventFloatp)
{ {
const LLTrace::TraceType<LLTrace::EventAccumulator>& event_stat = *mEventFloatp; const LLTrace::TraceType<LLTrace::EventAccumulator>& event_stat = *mEventFloatp;
unit_label = mUnitLabel.empty() ? event_stat.getUnitLabel() : mUnitLabel; unit_label = mUnitLabel.empty() ? event_stat.getUnitLabel() : mUnitLabel;
current = last_frame_recording.getLastValue(event_stat); current = last_frame_recording.getLastValue(event_stat);
min = frame_recording.getPeriodMin(event_stat, num_frames); min = frame_recording.getPeriodMin(event_stat, num_frames);
max = frame_recording.getPeriodMax(event_stat, num_frames); max = frame_recording.getPeriodMax(event_stat, num_frames);
mean = frame_recording.getPeriodMean(event_stat, num_frames); mean = frame_recording.getPeriodMean(event_stat, num_frames);
num_rapid_changes = calc_num_rapid_changes(frame_recording, event_stat, CHANGE_WINDOW); num_rapid_changes = calc_num_rapid_changes(frame_recording, event_stat, RAPID_CHANGE_WINDOW);
display_value = mean;
} }
else if (mSampleFloatp) else if (mSampleFloatp)
{ {
const LLTrace::TraceType<LLTrace::SampleAccumulator>& sample_stat = *mSampleFloatp; const LLTrace::TraceType<LLTrace::SampleAccumulator>& sample_stat = *mSampleFloatp;
unit_label = mUnitLabel.empty() ? sample_stat.getUnitLabel() : mUnitLabel; unit_label = mUnitLabel.empty() ? sample_stat.getUnitLabel() : mUnitLabel;
current = last_frame_recording.getLastValue(sample_stat); current = last_frame_recording.getLastValue(sample_stat);
min = frame_recording.getPeriodMin(sample_stat, num_frames); min = frame_recording.getPeriodMin(sample_stat, num_frames);
max = frame_recording.getPeriodMax(sample_stat, num_frames); max = frame_recording.getPeriodMax(sample_stat, num_frames);
mean = frame_recording.getPeriodMean(sample_stat, num_frames); mean = frame_recording.getPeriodMean(sample_stat, num_frames);
num_rapid_changes = calc_num_rapid_changes(frame_recording, sample_stat, CHANGE_WINDOW); num_rapid_changes = calc_num_rapid_changes(frame_recording, sample_stat, RAPID_CHANGE_WINDOW);
}
if (mLastDisplayValueTimer.getElapsedTimeF32() > MIN_VALUE_UPDATE_TIME) if (num_rapid_changes / RAPID_CHANGE_WINDOW > MAX_RAPID_CHANGES_PER_SEC)
{ {
mLastDisplayValueTimer.reset(); display_value = mean;
display_value = (num_rapid_changes > MAX_RAPID_CHANGES)
? mean
: current;
mLastDisplayValue = display_value;
} }
else else
{ {
display_value = mLastDisplayValue; display_value = current;
// always display current value, don't rate limit
mLastDisplayValue = current;
}
} }
LLRect bar_rect; LLRect bar_rect;
...@@ -365,7 +386,17 @@ void LLStatBar::draw() ...@@ -365,7 +386,17 @@ void LLStatBar::draw()
mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, mMaxBar, 0.05f); mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, mMaxBar, 0.05f);
mCurMinBar = LLSmoothInterpolation::lerp(mCurMinBar, mMinBar, 0.05f); mCurMinBar = LLSmoothInterpolation::lerp(mCurMinBar, mMinBar, 0.05f);
// rate limited updates
if (mLastDisplayValueTimer.getElapsedTimeF32() > MEAN_VALUE_UPDATE_TIME)
{
mLastDisplayValueTimer.reset();
drawLabelAndValue(display_value, unit_label, bar_rect); drawLabelAndValue(display_value, unit_label, bar_rect);
mLastDisplayValue = display_value;
}
else
{
drawLabelAndValue(mLastDisplayValue, unit_label, bar_rect);
}
if (mDisplayBar if (mDisplayBar
&& (mCountFloatp || mEventFloatp || mSampleFloatp)) && (mCountFloatp || mEventFloatp || mSampleFloatp))
......
...@@ -56,24 +56,7 @@ class LLStatBar : public LLView ...@@ -56,24 +56,7 @@ class LLStatBar : public LLView
Optional<std::string> stat; Optional<std::string> stat;
Optional<EOrientation> orientation; Optional<EOrientation> orientation;
Params() Params();
: label("label"),
unit_label("unit_label"),
bar_min("bar_min", 0.f),
bar_max("bar_max", 0.f),
tick_spacing("tick_spacing", 0.f),
decimal_digits("decimal_digits", 3),
show_bar("show_bar", false),
show_history("show_history", false),
scale_range("scale_range", true),
num_frames("num_frames", 200),
num_frames_short("num_frames_short", 20),
max_height("max_height", 100),
stat("stat"),
orientation("orientation", VERTICAL)
{
changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT);
}
}; };
LLStatBar(const Params&); LLStatBar(const Params&);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
setting="OpenDebugStatBasic"> setting="OpenDebugStatBasic">
<stat_bar name="fps" <stat_bar name="fps"
label="FPS" label="FPS"
unit_label="frames" unit_label="fps"
stat="FPS" stat="FPS"
decimal_digits="1" decimal_digits="1"
show_bar="true" show_bar="true"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment