Skip to content

Commit

Permalink
Optimize single_actor_batch, part 1
Browse files Browse the repository at this point in the history
Most speedups should be evident in situations with adds.

Also introduces a new flag to action_t called "dynamic_aoe". Should be
set to true on abilities that can dynamically change from single target
to multi-target during iteration (e.g., due to a buff)

Normal mode simulation should see no changes from this commit.
  • Loading branch information
navv1234 committed Mar 31, 2017
1 parent 6062c61 commit 859293f
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 71 deletions.
35 changes: 14 additions & 21 deletions engine/action/sc_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,20 +267,6 @@ struct action_execute_event_t : public player_event_t
}
};

struct aoe_target_list_callback_t
{
action_t* action;

aoe_target_list_callback_t( action_t* a ) :
action( a ) {}

void operator()(player_t*)
{
// Invalidate target cache
action -> target_cache.is_valid = false;
}
};

struct power_entry_without_aura
{
bool operator()( const spellpower_data_t* p )
Expand Down Expand Up @@ -437,6 +423,7 @@ action_t::action_t( action_e ty,
dynamic_tick_action( true), // WoD updates everything on tick by default. If you need snapshotted values for a periodic effect, use persistent multipliers.
interrupt_immediate_occurred(),
hit_any_target(),
dynamic_aoe( false ),
dot_behavior( DOT_REFRESH ),
ability_lag(),
ability_lag_stddev(),
Expand Down Expand Up @@ -2170,8 +2157,6 @@ void action_t::init()
sim -> out_debug.printf( "%s - radius %.1f - range - %.1f", name(), radius, range );
#endif

init_target_cache();

consume_per_tick_ = range::find_if( base_costs_per_tick, []( const double& d ) { return d != 0; } ) != base_costs_per_tick.end();

// Setup default target in init
Expand Down Expand Up @@ -2248,11 +2233,6 @@ bool action_t::init_finished()
return ret;
}

void action_t::init_target_cache()
{
sim -> target_non_sleeping_list.register_callback( aoe_target_list_callback_t( this ) );
}

// action_t::reset ==========================================================

void action_t::reset()
Expand Down Expand Up @@ -3661,3 +3641,16 @@ void action_t::acquire_target( retarget_event_e /* event */,
target_cache.is_valid = false;
}
}

void action_t::activate()
{
// On AOE actions, enable target cache regeneration when state of the enemy targets change. Also
// explicitly enable the target cache invalidator if the ability is flagged as being dynamic aoe
// (changes the number of targets hit dynamically during combat)
if ( n_targets() != 0 || dynamic_aoe )
{
sim -> target_non_sleeping_list.register_callback( [ this ]( player_t* ) {
target_cache.is_valid = false;
} );
}
}
36 changes: 14 additions & 22 deletions engine/action/sc_spell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,6 @@

#include "simulationcraft.hpp"

namespace {

struct aoe_player_list_callback_t
{
action_t* action;
aoe_player_list_callback_t( action_t* a ) : action( a ) {}

void operator()(player_t*)
{
// Invalidate target cache
action -> target_cache.is_valid = false;
}
};

} // unnamed namespace

// ==========================================================================
// Spell Base
// ==========================================================================
Expand Down Expand Up @@ -242,10 +226,14 @@ heal_t::heal_t( const std::string& token,
}
}

void heal_t::init_target_cache()
void heal_t::activate()
{
if ( aoe )
sim -> player_non_sleeping_list.register_callback( aoe_player_list_callback_t( this ) );
if ( n_targets() != 0 || dynamic_aoe )
{
sim -> player_non_sleeping_list.register_callback( [ this ]( player_t* ) {
target_cache.is_valid = false;
} );
}
}

// heal_t::parse_effect_data ================================================
Expand Down Expand Up @@ -634,10 +622,14 @@ absorb_t::absorb_t( const std::string& token,
stats -> type = STATS_ABSORB;
}

void absorb_t::init_target_cache()
void absorb_t::activate()
{
if ( aoe )
sim -> player_non_sleeping_list.register_callback( aoe_player_list_callback_t( this ) );
if ( n_targets() != 0 || dynamic_aoe )
{
sim -> player_non_sleeping_list.register_callback( [ this ]( player_t* ) {
target_cache.is_valid = false;
} );
}
}

// absorb_t::execute ========================================================
Expand Down
2 changes: 2 additions & 0 deletions engine/class_modules/sc_death_knight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5347,6 +5347,8 @@ struct scourge_strike_base_t : public death_knight_melee_attack_t
//
// TODO: Changed in 7.1.5, new probability distribution unknown/untested
instructors_chance = { { .3, .4, .2, .1 } };

dynamic_aoe = true; // Dynamically becomes AOE if you stand in Defile/DnD
}

int n_targets() const override
Expand Down
12 changes: 10 additions & 2 deletions engine/class_modules/sc_demon_hunter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ class demon_hunter_t : public player_t
void invalidate_cache( cache_e ) override;
resource_e primary_resource() const override;
role_e primary_role() const override;
void activate() override;

// custom demon_hunter_t init functions
private:
Expand Down Expand Up @@ -5576,14 +5577,21 @@ bool demon_hunter_t::create_actions()
annihilation_dmg = new damage_calc_helper_t( annihilation_attacks );
}

return ca;
}

// demon_hunter_t::activate =================================================

void demon_hunter_t::activate()
{
player_t::activate();

if ( blade_dance_dmg || death_sweep_dmg || chaos_strike_dmg ||
annihilation_dmg )
{
sim -> target_non_sleeping_list.register_callback(
damage_calc_invalidate_callback_t( this ) );
}

return ca;
}

// demon_hunter_t::create_buffs =============================================
Expand Down
19 changes: 17 additions & 2 deletions engine/class_modules/sc_druid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,10 @@ struct druid_t : public player_t
starshards( 0.0 ),
predator_rppm_rate( 0.0 ),
initial_astral_power( 0 ),
t20_2pc(false),
t20_4pc(false),
initial_moon_stage( NEW_MOON ),
ahhhhh_the_great_outdoors( true ),
t20_2pc(false),
t20_4pc(false),
active( active_actions_t() ),
pet_fey_moonwing(),
force_of_nature(),
Expand Down Expand Up @@ -3308,6 +3308,17 @@ struct maim_t : public cat_attack_t
weapon_multiplier = data().effectN( 3 ).pp_combo_points() / 100.0;
}

void init() override
{
cat_attack_t::init();

// Fiery Red Maimers legendary allows maim to dynamically change the number of targets. Note,
// needs to be done in action_t::init override, since special effects (including the fallback
// buff) are initialized after create_actions() (which is the method that calls maim_t
// constructor if the user has a Maim action in the APL).
dynamic_aoe = p() -> buff.fiery_red_maimers -> default_chance != 0;
}

int n_targets() const override
{
int n = cat_attack_t::n_targets();
Expand Down Expand Up @@ -3900,6 +3911,8 @@ struct mangle_t : public bear_attack_t
}

base_multiplier *= 1.0 + player -> artifact.vicious_bites.percent();

dynamic_aoe = true; // Incarnation increases number of targets dynamically
}

double composite_energize_amount( const action_state_t* s ) const override
Expand Down Expand Up @@ -4669,6 +4682,8 @@ struct wild_growth_t : public druid_heal_t
druid_heal_t( "wild_growth", p, p -> find_class_spell( "Wild Growth" ), options_str )
{
ignore_false_positive = true;

dynamic_aoe = true; // Incarnation increases number of targets dynamically
}

int n_targets() const override
Expand Down
30 changes: 19 additions & 11 deletions engine/class_modules/sc_mage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ struct mage_t : public player_t
virtual void arise() override;
virtual action_t* select_action( const action_priority_list_t& ) override;
virtual void copy_from( player_t* ) override;
void activate() override;

target_specific_t<mage_td_t> target_data;

Expand Down Expand Up @@ -8337,39 +8338,46 @@ void mage_t::init_benefits()
}
}

// mage_t::init_stats =========================================================
// mage_t::activate ===========================================================

void mage_t::init_stats()
void mage_t::activate()
{
player_t::init_stats();

// Cache Icy Veins haste multiplier for performance reasons
double haste = buffs.icy_veins -> data().effectN( 1 ).percent();
iv_haste = 1.0 / ( 1.0 + haste );
player_t::activate();

// Register target reset callback here (anywhere later on than in
// constructor) so older GCCs are happy
// Forcibly reset mage's current target, if it dies.
sim->target_non_sleeping_list.register_callback( [this]( player_t* ) {
sim -> target_non_sleeping_list.register_callback( [ this ]( player_t* ) {

// If the mage's current target is still alive, bail out early.
if ( range::find( sim->target_non_sleeping_list, current_target ) !=
sim->target_non_sleeping_list.end() )
sim -> target_non_sleeping_list.end() )
{
return;
}

if ( sim->debug )
if ( sim -> debug )
{
sim->out_debug.printf(
"%s current target %s died. Resetting target to %s.", name(),
current_target->name(), target->name() );
current_target -> name(), target -> name() );
}

current_target = target;
} );
}

// mage_t::init_stats =========================================================

void mage_t::init_stats()
{
player_t::init_stats();

// Cache Icy Veins haste multiplier for performance reasons
double haste = buffs.icy_veins -> data().effectN( 1 ).percent();
iv_haste = 1.0 / ( 1.0 + haste );
}


// mage_t::init_assessors =====================================================

Expand Down
15 changes: 13 additions & 2 deletions engine/class_modules/sc_monk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ struct monk_t: public player_t
virtual void assess_heal( school_e, dmg_e, action_state_t* s) override;
virtual void invalidate_cache( cache_e ) override;
virtual void init_action_list() override;
void activate() override;
virtual bool has_t18_class_trinket() const override;
virtual expr_t* create_expression( action_t* a, const std::string& name_str ) override;
virtual monk_td_t* get_target_data( player_t* target ) const override
Expand Down Expand Up @@ -7710,15 +7711,25 @@ void monk_t::create_pets()

if ( specialization() == MONK_WINDWALKER && find_action( "storm_earth_and_fire" ) )
{
sim -> target_non_sleeping_list.register_callback( actions::sef_despawn_cb_t( this ) );

pet.sef[ SEF_FIRE ] = new pets::storm_earth_and_fire_pet_t( "fire_spirit", sim, this, true );
// The player BECOMES the Storm Spirit
// SEF EARTH was changed from 2-handed user to dual welding in Legion
pet.sef[ SEF_EARTH ] = new pets::storm_earth_and_fire_pet_t( "earth_spirit", sim, this, true );
}
}

// monk_t::activate =========================================================

void monk_t::activate()
{
player_t::activate();

if ( specialization() == MONK_WINDWALKER && find_action( "storm_earth_and_fire" ) )
{
sim -> target_non_sleeping_list.register_callback( actions::sef_despawn_cb_t( this ) );
}
}

// monk_t::init_spells ======================================================

void monk_t::init_spells()
Expand Down
4 changes: 3 additions & 1 deletion engine/class_modules/sc_paladin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3102,9 +3102,11 @@ struct zeal_t : public holy_power_generator_t

// TODO: figure out wtf happened to this spell data
hasted_cd = hasted_gcd = true;

dynamic_aoe = true; // Zeal buff changes the number of targets dynamically
}

virtual int n_targets() const override
int n_targets() const override
{
if ( p() -> buffs.zeal -> stack() )
return 1 + p() -> buffs.zeal -> stack();
Expand Down
6 changes: 6 additions & 0 deletions engine/class_modules/sc_warlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2465,6 +2465,12 @@ struct warlock_spell_t: public spell_t
}
}

// Havoc makes single-target spells potentially AOE
if ( aoe == 0 && p() -> specialization() == WARLOCK_DESTRUCTION )
{
dynamic_aoe = true;
}

return spell_t::init_finished();
}

Expand Down
Loading

0 comments on commit 859293f

Please sign in to comment.