Save 2 bytes per PlotItem.

Memory savings:

android     2614 MB -> 2487 MB (95%)
chicken     1932 MB -> 1852 MB (95%)
mem         6067 MB -> 5747 MB (94%)
q3bsp-mt    5059 MB -> 5017 MB (99%)
q3bsp-st    1211 MB -> 1171 MB (96%)
This commit is contained in:
Bartosz Taudul 2019-11-03 14:50:11 +01:00
parent 29dcc5c8bc
commit d9c3238462
3 changed files with 45 additions and 70 deletions

View File

@ -386,6 +386,15 @@ struct MessageData
enum { MessageDataSize = sizeof( MessageData ) }; enum { MessageDataSize = sizeof( MessageData ) };
struct PlotItem
{
Int48 time;
double val;
};
enum { PlotItemSize = sizeof( PlotItem ) };
#pragma pack() #pragma pack()
@ -452,12 +461,6 @@ struct LockHighlight
bool blocked; bool blocked;
}; };
struct PlotItem
{
int64_t time;
double val;
};
enum class PlotType : uint8_t enum class PlotType : uint8_t
{ {
User, User,

View File

@ -4812,8 +4812,8 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
ImGui::Text( "Plot \"%s\"", txt ); ImGui::Text( "Plot \"%s\"", txt );
ImGui::Separator(); ImGui::Separator();
const auto first = v->data.front().time; const auto first = v->data.front().time.Val();
const auto last = v->data.back().time; const auto last = v->data.back().time.Val();
const auto activity = last - first; const auto activity = last - first;
const auto traceLen = m_worker.GetLastTime(); const auto traceLen = m_worker.GetLastTime();
@ -4829,8 +4829,8 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
TextFocused( "Max value:", FormatPlotValue( v->max, v->type ) ); TextFocused( "Max value:", FormatPlotValue( v->max, v->type ) );
TextFocused( "Data/second:", RealToString( double( v->data.size() ) / activity * 1000000000ll, true ) ); TextFocused( "Data/second:", RealToString( double( v->data.size() ) / activity * 1000000000ll, true ) );
const auto it = std::lower_bound( v->data.begin(), v->data.end(), last - 1000000000ll * 10, [] ( const auto& l, const auto& r ) { return l.time < r; } ); const auto it = std::lower_bound( v->data.begin(), v->data.end(), last - 1000000000ll * 10, [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
const auto tr10 = last - it->time; const auto tr10 = last - it->time.Val();
if( tr10 != 0 ) if( tr10 != 0 )
{ {
TextFocused( "D/s (10s):", RealToString( double( std::distance( it, v->data.end() ) ) / tr10 * 1000000000ll, true ) ); TextFocused( "D/s (10s):", RealToString( double( std::distance( it, v->data.end() ) ) / tr10 * 1000000000ll, true ) );
@ -4896,8 +4896,8 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
} }
} }
auto it = std::lower_bound( vec.begin(), vec.end(), m_vd.zvStart - m_worker.GetDelay(), [] ( const auto& l, const auto& r ) { return l.time < r; } ); auto it = std::lower_bound( vec.begin(), vec.end(), m_vd.zvStart - m_worker.GetDelay(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
auto end = std::lower_bound( it, vec.end(), m_vd.zvEnd + m_worker.GetResolution(), [] ( const auto& l, const auto& r ) { return l.time < r; } ); auto end = std::lower_bound( it, vec.end(), m_vd.zvEnd + m_worker.GetResolution(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
if( end != vec.end() ) end++; if( end != vec.end() ) end++;
if( it != vec.begin() ) it--; if( it != vec.begin() ) it--;
@ -4915,42 +4915,11 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
auto tmp = it; auto tmp = it;
++tmp; ++tmp;
const auto sz = end - tmp; const auto sz = end - tmp;
#ifdef __AVX2__
__m256d vmin = _mm256_set1_pd( min );
__m256d vmax = vmin;
const auto ssz = sz / 4;
for( ptrdiff_t i=0; i<ssz; i++ )
{
__m256d v0 = _mm256_loadu_pd( (const double*)(tmp+0) );
__m256d v1 = _mm256_loadu_pd( (const double*)(tmp+2) );
__m256d v = _mm256_unpackhi_pd( v0, v1 );
vmin = _mm256_min_pd( vmin, v );
vmax = _mm256_max_pd( vmax, v );
tmp += 4;
}
__m256d min0 = _mm256_shuffle_pd( vmin, vmin, 5 );
__m256d max0 = _mm256_shuffle_pd( vmax, vmax, 5 );
__m256d min1 = _mm256_min_pd( vmin, min0 );
__m256d max1 = _mm256_max_pd( vmax, max0 );
__m256d min2 = _mm256_permute4x64_pd( min1, _MM_SHUFFLE( 0, 0, 2, 2 ) );
__m256d max2 = _mm256_permute4x64_pd( max1, _MM_SHUFFLE( 0, 0, 2, 2 ) );
__m256d min3 = _mm256_min_pd( min1, min2 );
__m256d max3 = _mm256_max_pd( max1, max2 );
min = _mm256_cvtsd_f64( min3 );
max = _mm256_cvtsd_f64( max3 );
const auto lsz = sz % 4;
for( ptrdiff_t i=0; i<lsz; i++ )
{
min = tmp[i].val < min ? tmp[i].val : min;
max = tmp[i].val > max ? tmp[i].val : max;
}
#else
for( ptrdiff_t i=0; i<sz; i++ ) for( ptrdiff_t i=0; i<sz; i++ )
{ {
min = tmp[i].val < min ? tmp[i].val : min; min = tmp[i].val < min ? tmp[i].val : min;
max = tmp[i].val > max ? tmp[i].val : max; max = tmp[i].val > max ? tmp[i].val : max;
} }
#endif
} }
if( min == max ) if( min == max )
{ {
@ -4987,7 +4956,7 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
if( it == vec.begin() ) if( it == vec.begin() )
{ {
const auto x = ( it->time - m_vd.zvStart ) * pxns; const auto x = ( it->time.Val() - m_vd.zvStart ) * pxns;
const auto y = PlotHeight - ( it->val - min ) * revrange * PlotHeight; const auto y = PlotHeight - ( it->val - min ) * revrange * PlotHeight;
DrawPlotPoint( wpos, x, y, offset, 0xFF44DDDD, hover, false, it, 0, false, v->type, PlotHeight ); DrawPlotPoint( wpos, x, y, offset, 0xFF44DDDD, hover, false, it, 0, false, v->type, PlotHeight );
} }
@ -4998,8 +4967,8 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
ptrdiff_t skip = 0; ptrdiff_t skip = 0;
while( it < end ) while( it < end )
{ {
const auto x0 = ( prevx->time - m_vd.zvStart ) * pxns; const auto x0 = ( prevx->time.Val() - m_vd.zvStart ) * pxns;
const auto x1 = ( it->time - m_vd.zvStart ) * pxns; const auto x1 = ( it->time.Val() - m_vd.zvStart ) * pxns;
const auto y0 = PlotHeight - ( prevy->val - min ) * revrange * PlotHeight; const auto y0 = PlotHeight - ( prevy->val - min ) * revrange * PlotHeight;
const auto y1 = PlotHeight - ( it->val - min ) * revrange * PlotHeight; const auto y1 = PlotHeight - ( it->val - min ) * revrange * PlotHeight;
@ -5007,7 +4976,7 @@ int View::DrawPlots( int offset, double pxns, const ImVec2& wpos, bool hover, fl
const auto rx = skip == 0 ? 2.0 : ( skip == 1 ? 2.5 : 4.0 ); const auto rx = skip == 0 ? 2.0 : ( skip == 1 ? 2.5 : 4.0 );
auto range = std::upper_bound( it, end, int64_t( it->time + nspx * rx ), [] ( const auto& l, const auto& r ) { return l < r.time; } ); auto range = std::upper_bound( it, end, int64_t( it->time.Val() + nspx * rx ), [] ( const auto& l, const auto& r ) { return l < r.time.Val(); } );
assert( range > it ); assert( range > it );
const auto rsz = std::distance( it, range ); const auto rsz = std::distance( it, range );
if( rsz == 1 ) if( rsz == 1 )
@ -5174,8 +5143,8 @@ void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint
const MemEvent* ev = nullptr; const MemEvent* ev = nullptr;
if( change > 0 ) if( change > 0 )
{ {
auto it = std::lower_bound( mem.data.begin(), mem.data.end(), item->time, [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } ); auto it = std::lower_bound( mem.data.begin(), mem.data.end(), item->time.Val(), [] ( const auto& lhs, const auto& rhs ) { return lhs.TimeAlloc() < rhs; } );
if( it != mem.data.end() && it->TimeAlloc() == item->time ) if( it != mem.data.end() && it->TimeAlloc() == item->time.Val() )
{ {
ev = it; ev = it;
} }
@ -5183,8 +5152,8 @@ void View::DrawPlotPoint( const ImVec2& wpos, float x, float y, int offset, uint
else else
{ {
const auto& data = mem.data; const auto& data = mem.data;
auto it = std::lower_bound( mem.frees.begin(), mem.frees.end(), item->time, [&data] ( const auto& lhs, const auto& rhs ) { return data[lhs].TimeFree() < rhs; } ); auto it = std::lower_bound( mem.frees.begin(), mem.frees.end(), item->time.Val(), [&data] ( const auto& lhs, const auto& rhs ) { return data[lhs].TimeFree() < rhs; } );
if( it != mem.frees.end() && data[*it].TimeFree() == item->time ) if( it != mem.frees.end() && data[*it].TimeFree() == item->time.Val() )
{ {
ev = &data[*it]; ev = &data[*it];
} }

View File

@ -1062,7 +1062,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
int64_t refTime = 0; int64_t refTime = 0;
for( uint64_t j=0; j<psz; j++ ) for( uint64_t j=0; j<psz; j++ )
{ {
pd->data[j].time = ReadTimeOffset( f, refTime ); pd->data[j].time.SetVal( ReadTimeOffset( f, refTime ) );
f.Read( pd->data[j].val ); f.Read( pd->data[j].val );
} }
} }
@ -1071,16 +1071,19 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
int64_t refTime = -m_data.baseTime; int64_t refTime = -m_data.baseTime;
for( uint64_t j=0; j<psz; j++ ) for( uint64_t j=0; j<psz; j++ )
{ {
pd->data[j].time = ReadTimeOffset( f, refTime ); pd->data[j].time.SetVal( ReadTimeOffset( f, refTime ) );
f.Read( pd->data[j].val ); f.Read( pd->data[j].val );
} }
} }
else else
{ {
f.Read( pd->data.data(), psz * sizeof( PlotItem ) );
for( uint64_t j=0; j<psz; j++ ) for( uint64_t j=0; j<psz; j++ )
{ {
pd->data[j].time -= m_data.baseTime; uint64_t t;
f.Read( t );
t -= m_data.baseTime;
pd->data[j].time.SetVal( t );
f.Read( pd->data[j].val );
} }
} }
m_data.plots.Data().push_back_no_space_check( pd ); m_data.plots.Data().push_back_no_space_check( pd );
@ -1100,7 +1103,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
} }
uint64_t psz; uint64_t psz;
f.Read( psz ); f.Read( psz );
f.Skip( psz * sizeof( PlotItem ) ); f.Skip( psz * ( sizeof( uint64_t ) + sizeof( double ) ) );
} }
} }
@ -3223,13 +3226,13 @@ void Worker::InsertPlot( PlotData* plot, int64_t time, double val )
{ {
plot->min = val; plot->min = val;
plot->max = val; plot->max = val;
plot->data.push_back( { time, val } ); plot->data.push_back( { Int48( time ), val } );
} }
else if( plot->data.back().time < time ) else if( plot->data.back().time.Val() < time )
{ {
if( plot->min > val ) plot->min = val; if( plot->min > val ) plot->min = val;
else if( plot->max < val ) plot->max = val; else if( plot->max < val ) plot->max = val;
plot->data.push_back_non_empty( { time, val } ); plot->data.push_back_non_empty( { Int48( time ), val } );
} }
else else
{ {
@ -3238,11 +3241,11 @@ void Worker::InsertPlot( PlotData* plot, int64_t time, double val )
if( plot->postpone.empty() ) if( plot->postpone.empty() )
{ {
plot->postponeTime = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); plot->postponeTime = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
plot->postpone.push_back( { time, val } ); plot->postpone.push_back( { Int48( time ), val } );
} }
else else
{ {
plot->postpone.push_back_non_empty( { time, val } ); plot->postpone.push_back_non_empty( { Int48( time ), val } );
} }
} }
} }
@ -3253,7 +3256,7 @@ void Worker::HandlePlotName( uint64_t name, char* str, size_t sz )
m_data.plots.StringDiscovered( name, sl, m_data.strings, [this] ( PlotData* dst, PlotData* src ) { m_data.plots.StringDiscovered( name, sl, m_data.strings, [this] ( PlotData* dst, PlotData* src ) {
for( auto& v : src->data ) for( auto& v : src->data )
{ {
InsertPlot( dst, v.time, v.val ); InsertPlot( dst, v.time.Val(), v.val );
} }
} ); } );
} }
@ -3277,16 +3280,16 @@ void Worker::HandlePostponedPlots()
if( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count() - plot->postponeTime < 100 ) continue; if( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count() - plot->postponeTime < 100 ) continue;
auto& dst = plot->data; auto& dst = plot->data;
#ifdef MY_LIBCPP_SUCKS #ifdef MY_LIBCPP_SUCKS
pdqsort_branchless( src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l.time < r.time; } ); pdqsort_branchless( src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r.time.Val(); } );
#else #else
std::sort( std::execution::par_unseq, src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l.time < r.time; } ); std::sort( std::execution::par_unseq, src.begin(), src.end(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r.time.Val(); } );
#endif #endif
const auto ds = std::lower_bound( dst.begin(), dst.end(), src.front().time, [] ( const auto& l, const auto& r ) { return l.time < r; } ); const auto ds = std::lower_bound( dst.begin(), dst.end(), src.front().time.Val(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
const auto dsd = std::distance( dst.begin(), ds ) ; const auto dsd = std::distance( dst.begin(), ds ) ;
const auto de = std::lower_bound( ds, dst.end(), src.back().time, [] ( const auto& l, const auto& r ) { return l.time < r; } ); const auto de = std::lower_bound( ds, dst.end(), src.back().time.Val(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r; } );
const auto ded = std::distance( dst.begin(), de ); const auto ded = std::distance( dst.begin(), de );
dst.insert( de, src.begin(), src.end() ); dst.insert( de, src.begin(), src.end() );
std::inplace_merge( dst.begin() + dsd, dst.begin() + ded, dst.begin() + ded + src.size(), [] ( const auto& l, const auto& r ) { return l.time < r.time; } ); std::inplace_merge( dst.begin() + dsd, dst.begin() + ded, dst.begin() + ded + src.size(), [] ( const auto& l, const auto& r ) { return l.time.Val() < r.time.Val(); } );
src.clear(); src.clear();
} }
} }
@ -4596,7 +4599,7 @@ void Worker::ProcessSysTime( const QueueSysTime& ev )
else else
{ {
assert( !m_sysTimePlot->data.empty() ); assert( !m_sysTimePlot->data.empty() );
assert( m_sysTimePlot->data.back().time <= time ); assert( m_sysTimePlot->data.back().time.Val() <= time );
if( m_sysTimePlot->min > val ) m_sysTimePlot->min = val; if( m_sysTimePlot->min > val ) m_sysTimePlot->min = val;
else if( m_sysTimePlot->max < val ) m_sysTimePlot->max = val; else if( m_sysTimePlot->max < val ) m_sysTimePlot->max = val;
m_sysTimePlot->data.push_back_non_empty( { time, val } ); m_sysTimePlot->data.push_back_non_empty( { time, val } );
@ -4741,7 +4744,7 @@ void Worker::MemAllocChanged( int64_t time )
else else
{ {
assert( !m_data.memory.plot->data.empty() ); assert( !m_data.memory.plot->data.empty() );
assert( m_data.memory.plot->data.back().time <= time ); assert( m_data.memory.plot->data.back().time.Val() <= time );
if( m_data.memory.plot->min > val ) m_data.memory.plot->min = val; if( m_data.memory.plot->min > val ) m_data.memory.plot->min = val;
else if( m_data.memory.plot->max < val ) m_data.memory.plot->max = val; else if( m_data.memory.plot->max < val ) m_data.memory.plot->max = val;
m_data.memory.plot->data.push_back_non_empty( { time, val } ); m_data.memory.plot->data.push_back_non_empty( { time, val } );
@ -5576,7 +5579,7 @@ void Worker::Write( FileWrite& f )
f.Write( &sz, sizeof( sz ) ); f.Write( &sz, sizeof( sz ) );
for( auto& v : plot->data ) for( auto& v : plot->data )
{ {
WriteTimeOffset( f, refTime, v.time ); WriteTimeOffset( f, refTime, v.time.Val() );
f.Write( &v.val, sizeof( v.val ) ); f.Write( &v.val, sizeof( v.val ) );
} }
} }