Skip to content

Commit

Permalink
Field enumeration perf (CleverRaven#31686)
Browse files Browse the repository at this point in the history
* Templatize shift_bitset_cache

* Establish and use a bitset cache for which submaps contain active fields
  • Loading branch information
kevingranade authored and ZhilkinSerg committed Jun 23, 2019
1 parent 2486010 commit dc3475c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 30 deletions.
46 changes: 31 additions & 15 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2705,6 +2705,7 @@ void map::decay_fields_and_scent( const time_duration &amount )
<< abs_sub.x + smx << "," << abs_sub.y + smy << "," << abs_sub.z
<< "has " << to_proc << " field_count";
}
get_cache( smz ).field_cache.reset( smx + ( smy * MAPSIZE ) );
// This submap has no fields
continue;
}
Expand Down Expand Up @@ -5411,7 +5412,10 @@ bool map::add_field( const tripoint &p, const field_id type, int intensity,

if( current_submap->fld[l.x][l.y].add_field( type, intensity, age ) ) {
//Only adding it to the count if it doesn't exist.
current_submap->field_count++;
if( ! current_submap->field_count++ ) {
get_cache( p.z ).field_cache.set( static_cast<size_t>( p.x / SEEX + ( (
p.y / SEEX ) * MAPSIZE ) ) );
}
}

if( g != nullptr && this == &g->m && p == g->u.pos() ) {
Expand Down Expand Up @@ -5446,7 +5450,10 @@ void map::remove_field( const tripoint &p, const field_id field_to_remove )

if( current_submap->fld[l.x][l.y].remove_field( field_to_remove ) ) {
// Only adjust the count if the field actually existed.
current_submap->field_count--;
if( ! --current_submap->field_count ) {
get_cache( p.z ).field_cache.reset( static_cast<size_t>( p.x / SEEX + ( (
p.y / SEEX ) * MAPSIZE ) ) );
}
const auto &fdata = all_field_types_enum_list[ field_to_remove ];
for( bool i : fdata.transparent ) {
if( !i ) {
Expand Down Expand Up @@ -6478,31 +6485,36 @@ void map::shift_traps( const tripoint &shift )
}
}

void shift_map_memory_seen_cache(
std::bitset<MAPSIZE_X *MAPSIZE_Y> &map_memory_seen_cache,
const int sx, const int sy )
template<int SIZE, int MULTIPLIER>
void shift_bitset_cache( std::bitset<SIZE *SIZE> &cache, const int sx, const int sy )
{
// sx shifts by SEEX rows, sy shifts by SEEX columns.
int shift_amount = ( sx * SEEX ) + ( sy * MAPSIZE_Y * SEEX );
// sx shifts by MULTIPLIER rows, sy shifts by MULTIPLIER columns.
int shift_amount = ( sx * MULTIPLIER ) + ( sy * SIZE * MULTIPLIER );
if( shift_amount > 0 ) {
map_memory_seen_cache >>= static_cast<size_t>( shift_amount );
cache >>= static_cast<size_t>( shift_amount );
} else if( shift_amount < 0 ) {
map_memory_seen_cache <<= static_cast<size_t>( -shift_amount );
cache <<= static_cast<size_t>( -shift_amount );
}
// Shifting in the y direction shifted in 0 values, no no additional clearing is necessary, but
// a shift in the x direction makes values "wrap" to the next row, and they need to be zeroed.
if( sx == 0 ) {
return;
}
const size_t x_offset = ( sx > 0 ) ? MAPSIZE_X - SEEX : 0;
for( size_t y = 0; y < MAPSIZE_X; ++y ) {
size_t y_offset = y * MAPSIZE_X;
for( size_t x = 0; x < SEEX; ++x ) {
map_memory_seen_cache.reset( y_offset + x_offset + x );
const size_t x_offset = ( sx > 0 ) ? SIZE - MULTIPLIER : 0;
for( size_t y = 0; y < SIZE; ++y ) {
size_t y_offset = y * SIZE;
for( size_t x = 0; x < MULTIPLIER; ++x ) {
cache.reset( y_offset + x_offset + x );
}
}
}

template void
shift_bitset_cache<MAPSIZE_X, SEEX>( std::bitset<MAPSIZE_X *MAPSIZE_X> &cache,
const int sx, const int sy );
template void
shift_bitset_cache<MAPSIZE, 1>( std::bitset<MAPSIZE *MAPSIZE> &cache, const int sx, const int sy );

void map::shift( const int sx, const int sy )
{
// Special case of 0-shift; refresh the map
Expand Down Expand Up @@ -6540,7 +6552,8 @@ void map::shift( const int sx, const int sy )
// Clear vehicle list and rebuild after shift
clear_vehicle_cache( gridz );
clear_vehicle_list( gridz );
shift_map_memory_seen_cache( get_cache( gridz ).map_memory_seen_cache, sx, sy );
shift_bitset_cache<MAPSIZE_X, SEEX>( get_cache( gridz ).map_memory_seen_cache, sx, sy );
shift_bitset_cache<MAPSIZE, 1>( get_cache( gridz ).field_cache, sx, sy );
if( sx >= 0 ) {
for( int gridx = 0; gridx < my_MAPSIZE; gridx++ ) {
if( sy >= 0 ) {
Expand Down Expand Up @@ -6781,6 +6794,9 @@ void map::loadn( const int gridx, const int gridy, const int gridz, const bool u
if( !tmpsub->active_items.empty() ) {
submaps_with_active_items.emplace( absx, absy, gridz );
}
if( tmpsub->field_count > 0 ) {
get_cache( gridz ).field_cache.set( gridx + ( gridy * MAPSIZE ) );
}
// Destroy bugged no-part vehicles
auto &veh_vec = tmpsub->vehicles;
for( auto iter = veh_vec.begin(); iter != veh_vec.end(); ) {
Expand Down
6 changes: 3 additions & 3 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ struct level_cache {
float camera_cache[MAPSIZE_X][MAPSIZE_Y];
lit_level visibility_cache[MAPSIZE_X][MAPSIZE_Y];
std::bitset<MAPSIZE_X *MAPSIZE_Y> map_memory_seen_cache;
std::bitset<MAPSIZE *MAPSIZE> field_cache;

bool veh_in_active_range;
bool veh_exists_at[MAPSIZE_X][MAPSIZE_Y];
Expand Down Expand Up @@ -1692,9 +1693,8 @@ class map
bool need_draw_lower_floor( const tripoint &p );
};

void shift_map_memory_seen_cache(
std::bitset<MAPSIZE_X *MAPSIZE_Y> &map_memory_seen_cache,
const int sx, const int sy );
template<int SIZE, int MULTIPLIER>
void shift_bitset_cache( std::bitset<SIZE *SIZE> &cache, const int sx, const int sy );

std::vector<point> closest_points_first( int radius, point p );
std::vector<point> closest_points_first( int radius, int x, int y );
Expand Down
23 changes: 19 additions & 4 deletions src/map_field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ bool map::process_fields()
const int maxz = zlevels ? OVERMAP_HEIGHT : abs_sub.z;
for( int z = minz; z <= maxz; z++ ) {
bool zlev_dirty = false;
auto &field_cache = get_cache( z ).field_cache;
for( int x = 0; x < my_MAPSIZE; x++ ) {
for( int y = 0; y < my_MAPSIZE; y++ ) {
submap *const current_submap = get_submap_at_grid( { x, y, z } );
if( current_submap->field_count > 0 ) {
if( field_cache[ x + ( y * MAPSIZE ) ] ) {
submap *const current_submap = get_submap_at_grid( { x, y, z } );
const bool cur_dirty = process_fields_in_submap( current_submap, x, y, z );
zlev_dirty |= cur_dirty;
}
Expand Down Expand Up @@ -369,7 +370,7 @@ bool map::process_fields_in_submap( submap *const current_submap,
if( !all_field_types_enum_list[cur.get_field_type()].transparent[cur.get_field_intensity() - 1] ) {
dirty_transparency_cache = true;
}
current_submap->field_count--;
--current_submap->field_count;
curfield.remove_field( it++ );
continue;
}
Expand Down Expand Up @@ -1358,14 +1359,28 @@ bool map::process_fields_in_submap( submap *const current_submap,
cur.set_field_intensity( cur.get_field_intensity() - 1 );
}
if( !cur.is_field_alive() ) {
current_submap->field_count--;
--current_submap->field_count;
curfield.remove_field( it++ );
} else {
++it;
}
}
}
}
const int minz = zlevels ? -OVERMAP_DEPTH : abs_sub.z;
const int maxz = zlevels ? OVERMAP_HEIGHT : abs_sub.z;
for( int z = std::max( submap_z - 1, minz ); z <= std::min( submap_z + 1, maxz ); ++z ) {
auto &field_cache = get_cache( z ).field_cache;
for( int y = std::max( submap_y - 1, 0 ); y <= std::min( submap_y + 1, MAPSIZE - 1 ); ++y ) {
for( int x = std::max( submap_x - 1, 0 ); x <= std::min( submap_x + 1, MAPSIZE - 1 ); ++x ) {
if( get_submap_at_grid( { x, y, z } )->field_count > 0 ) {
field_cache.set( x + ( y * MAPSIZE ) );
} else {
field_cache.reset( x + ( y * MAPSIZE ) );
}
}
}
}
return dirty_transparency_cache;
}

Expand Down
16 changes: 8 additions & 8 deletions tests/map_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,56 +167,56 @@ TEST_CASE( "shift_map_memory_seen_cache" )
GIVEN( "all bits are set" ) {
test_cache.set();
WHEN( "positive x shift" ) {
shift_map_memory_seen_cache( test_cache, 1, 0 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, 1, 0 );
THEN( "last 12 columns are 0, rest are 1" ) {
check_quadrants( test_cache, last_twelve, 0,
true, false, true, false );
}
}
WHEN( "negative x shift" ) {
shift_map_memory_seen_cache( test_cache, -1, 0 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, -1, 0 );
THEN( "first 12 columns are 0, rest are 1" ) {
check_quadrants( test_cache, first_twelve, 0,
false, true, false, true );
}
}
WHEN( "positive y shift" ) {
shift_map_memory_seen_cache( test_cache, 0, 1 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, 0, 1 );
THEN( "last 12 rows are 0, rest are 1" ) {
check_quadrants( test_cache, 0, last_twelve,
true, true, false, false );
}
}
WHEN( "negative y shift" ) {
shift_map_memory_seen_cache( test_cache, 0, -1 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, 0, -1 );
THEN( "first 12 rows are 0, rest are 1" ) {
check_quadrants( test_cache, 0, first_twelve,
false, false, true, true );
}
}
WHEN( "positive x, positive y shift" ) {
shift_map_memory_seen_cache( test_cache, 1, 1 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, 1, 1 );
THEN( "last 12 columns and rows are 0, rest are 1" ) {
check_quadrants( test_cache, last_twelve, last_twelve,
true, false, false, false );
}
}
WHEN( "positive x, negative y shift" ) {
shift_map_memory_seen_cache( test_cache, 1, -1 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, 1, -1 );
THEN( "last 12 columns and first 12 rows are 0, rest are 1" ) {
check_quadrants( test_cache, last_twelve, first_twelve,
false, false, true, false );
}
}
WHEN( "negative x, positive y shift" ) {
shift_map_memory_seen_cache( test_cache, -1, 1 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, -1, 1 );
THEN( "first 12 columns and last 12 rows are 0, rest are 1" ) {
check_quadrants( test_cache, first_twelve, last_twelve,
false, true, false, false );
}
}
WHEN( "negative x, negative y shift" ) {
shift_map_memory_seen_cache( test_cache, -1, -1 );
shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, -1, -1 );
THEN( "first 12 columns and rows are 0, rest are 1" ) {
check_quadrants( test_cache, first_twelve, first_twelve,
false, false, false, true );
Expand Down

0 comments on commit dc3475c

Please sign in to comment.