Parcourir la source

Changed SC array to STL (#8834)

Decreased RAM usage for status changes from 7.832 bytes to 120 bytes, so by 7.712 bytes and therefore by 98,47%
Decreased server start RAM usage on RENEWAL from 646.072.000 bytes to 456.664.000 bytes, so by 189.408.000 bytes and therefore by 29,32% (measurements taken on Win10 x64)
Decreased server start RAM usage on PRE-RENEWAL from 432.724.000 bytes to 319.252.000 bytes, so by 113.472.000 bytes and therefore by 26,22% (measurements taken on Win10 x64)
During server runtime this means a decreased RAM usage by 98,47% for each affected block_list

Improved speed for saving active status changes
Improved speed for executing scripts of active status changes
Removed ERI use for status changes
Removed clearSCE to not interfere with the STL containers memory management
Removed sce variable reuse in status_change_end
Removed unnecessary sce exposure for SC_CLOSECONFINE/SC_CLOSECONFINE2/SC_CURSEDCIRCLE_ATKER

Fixed a bug in SC_STOP that caused the target's status to be recalculated instead of the source's (because of variable reuse)
Fixed a bug where the C++ destructors were called too early.

Thanks to @vstumpf for the preparations and his help!
Thanks to @datawulf and @Playtester for all the testing and feedback!
Lemongrass3110 il y a 1 mois
Parent
commit
75c88755dd
6 fichiers modifiés avec 520 ajouts et 280 suppressions
  1. 1 1
      src/map/battle.cpp
  2. 9 12
      src/map/chrif.cpp
  3. 56 2
      src/map/map.cpp
  4. 431 240
      src/map/status.cpp
  5. 23 19
      src/map/status.hpp
  6. 0 6
      src/map/unit.cpp

+ 1 - 1
src/map/battle.cpp

@@ -3652,7 +3652,7 @@ int32 battle_get_magic_element(struct block_list* src, struct block_list* target
 		case SU_CN_METEOR2:
 		case SH_HYUN_ROKS_BREEZE:
 		case SH_HYUN_ROK_CANNON:
-			if( sc != nullptr && sc->count > 0 ){
+			if( sc != nullptr && !sc->empty() ){
 				if( sc->getSCE( SC_COLORS_OF_HYUN_ROK_1 ) != nullptr ){
 					element = ELE_WATER;
 				}else if( sc->getSCE( SC_COLORS_OF_HYUN_ROK_2 ) != nullptr ){

+ 9 - 12
src/map/chrif.cpp

@@ -1272,7 +1272,7 @@ int32 chrif_updatefamelist_ack(int32 fd) {
 
 int32 chrif_save_scdata(map_session_data *sd) { //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex]
 #ifdef ENABLE_SC_SAVING
-	int32 i, count=0;
+	int32 count=0;
 	t_tick tick;
 	struct status_change_data data;
 	status_change *sc = &sd->sc;
@@ -1286,12 +1286,9 @@ int32 chrif_save_scdata(map_session_data *sd) { //parses the sc_data of the play
 	WFIFOL(char_fd,4) = sd->status.account_id;
 	WFIFOL(char_fd,8) = sd->status.char_id;
 
-	for (i = 0; i < SC_MAX; i++) {
-		auto sce = sc->getSCE(static_cast<sc_type>(i));
-		if (!sce)
-			continue;
-		if (sce->timer != INVALID_TIMER) {
-			timer = get_timer(sce->timer);
+	for( const auto& [type, sce] : *sc ){
+		if (sce.timer != INVALID_TIMER) {
+			timer = get_timer(sce.timer);
 			if (timer == nullptr || timer->func != status_change_timer)
 				continue;
 			if (DIFF_TICK(timer->tick,tick) > 0)
@@ -1300,11 +1297,11 @@ int32 chrif_save_scdata(map_session_data *sd) { //parses the sc_data of the play
 				data.tick = 0; //Negative tick does not necessarily mean that sc has expired
 		} else
 			data.tick = INFINITE_TICK; //Infinite duration
-		data.type = i;
-		data.val1 = sce->val1;
-		data.val2 = sce->val2;
-		data.val3 = sce->val3;
-		data.val4 = sce->val4;
+		data.type = type;
+		data.val1 = sce.val1;
+		data.val2 = sce.val2;
+		data.val3 = sce.val3;
+		data.val4 = sce.val4;
 		memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)),
 			&data, sizeof(struct status_change_data));
 		count++;

+ 56 - 2
src/map/map.cpp

@@ -228,6 +228,60 @@ int32 map_usercount(void)
 	return pc_db->size(pc_db);
 }
 
+void map_destroyblock( block_list* bl ){
+	if( bl == nullptr ){
+		return;
+	}
+
+	switch( bl->type ){
+		case BL_PC:
+			// Do not call the destructor here, it will be done in chrif_auth_delete
+			//reinterpret_cast<map_session_data*>( bl )->~map_session_data();
+			break;
+
+		case BL_MOB:
+			reinterpret_cast<mob_data*>( bl )->~mob_data();
+			break;
+
+		case BL_PET:
+			reinterpret_cast<pet_data*>( bl )->~pet_data();
+			break;
+
+		case BL_HOM:
+			reinterpret_cast<homun_data*>( bl )->~homun_data();
+			break;
+
+		case BL_MER:
+			reinterpret_cast<s_mercenary_data*>( bl )->~s_mercenary_data();
+			break;
+
+		case BL_ITEM:
+			reinterpret_cast<flooritem_data*>( bl )->~flooritem_data();
+			break;
+
+		case BL_SKILL:
+			reinterpret_cast<skill_unit*>( bl )->~skill_unit();
+			break;
+
+		case BL_NPC:
+			reinterpret_cast<npc_data*>( bl )->~npc_data();
+			break;
+
+		case BL_CHAT:
+			reinterpret_cast<chat_data*>( bl )->~chat_data();
+			break;
+
+		case BL_ELEM:
+			reinterpret_cast<s_elemental_data*>( bl )->~s_elemental_data();
+			break;
+
+		default:
+			ShowError( "map_destroyblock: unknown type %d\n", bl->type );
+			break;
+	}
+
+	aFree( bl );
+}
 
 /*==========================================
  * Attempt to free a map blocklist
@@ -237,7 +291,7 @@ int32 map_freeblock (struct block_list *bl)
 	nullpo_retr(block_free_lock, bl);
 	if (block_free_lock == 0 || block_free_count >= block_free_max)
 	{
-		aFree(bl);
+		map_destroyblock( bl );
 		bl = nullptr;
 		if (block_free_count >= block_free_max)
 			ShowWarning("map_freeblock: too many free block! %d %d\n", block_free_count, block_free_lock);
@@ -263,7 +317,7 @@ int32 map_freeblock_unlock (void)
 		int32 i;
 		for (i = 0; i < block_free_count; i++)
 		{
-			aFree(block_free[i]);
+			map_destroyblock( block_free[i] );
 			block_free[i] = nullptr;
 		}
 		block_free_count = 0;

Fichier diff supprimé car celui-ci est trop grand
+ 431 - 240
src/map/status.cpp


+ 23 - 19
src/map/status.hpp

@@ -3431,6 +3431,9 @@ struct sc_display_entry {
 struct status_change_entry {
 	int32 timer;
 	int32 val1,val2,val3,val4;
+
+	status_change_entry();
+	~status_change_entry();
 };
 
 ///Status change
@@ -3440,23 +3443,22 @@ public:
 	uint32 opt3;// skill state (bitfield)
 	uint16 opt1;// body state
 	uint16 opt2;// health state (bitfield)
-	unsigned char count;
 	sc_type lastEffect; // Used to check for stacking damageable SC on the same attack
 	int32 lastEffectTimer; // Timer for lastEffect
 	//! TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive.
 	struct {
-		uint8 move;
-		uint8 pickup;
-		uint8 drop;
-		uint8 cast;
-		uint8 chat;
-		uint8 equip;
-		uint8 unequip;
-		uint8 consume;
-		uint8 attack;
-		uint8 warp;
-		uint8 deathpenalty;
-		uint8 interact;
+		bool move;
+		bool pickup;
+		bool drop;
+		bool cast;
+		bool chat;
+		bool equip;
+		bool unequip;
+		bool consume;
+		bool attack;
+		bool warp;
+		bool deathpenalty;
+		bool interact;
 	} cant;/* status change state flags */
 	//int32 sg_id; //ID of the previous Storm gust that hit you
 	int16 comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point
@@ -3467,18 +3469,20 @@ public:
 	unsigned char sg_counter; //Storm gust counter (previous hits from storm gust)
 #endif
 private:
-	struct status_change_entry *data[SC_MAX];
-	std::pair<enum sc_type, struct status_change_entry *> lastStatus; // last-fetched status
+	std::unordered_map<enum sc_type, status_change_entry> data;
+	std::pair<enum sc_type, status_change_entry*> lastStatus; // last-fetched status
 
 public:
 	status_change();
 
-	status_change_entry * getSCE(enum sc_type type);
-	status_change_entry * getSCE(uint32 type);
-	status_change_entry * createSCE(enum sc_type type);
+	status_change_entry* getSCE( enum sc_type type );
+	status_change_entry* getSCE( uint32 type );
+	status_change_entry* createSCE( enum sc_type type );
 	void deleteSCE(enum sc_type type);
-	void clearSCE(enum sc_type type);
 	bool empty();
+	size_t size();
+	std::unordered_map<enum sc_type, status_change_entry>::const_iterator begin();
+	std::unordered_map<enum sc_type, status_change_entry>::const_iterator end();
 };
 #ifndef ONLY_CONSTANTS
 int32 status_damage( struct block_list *src, struct block_list *target, int64 dhp, int64 dsp, int64 dap, t_tick walkdelay, int32 flag, uint16 skill_id );

+ 0 - 6
src/map/unit.cpp

@@ -4010,7 +4010,6 @@ int32 unit_free(struct block_list *bl, clr_type clrtype)
 
 			skill_clear_unitgroup(bl);
 			status_change_clear(bl,1);
-			pd->~pet_data();
 			break;
 		}
 		case BL_MOB: {
@@ -4075,7 +4074,6 @@ int32 unit_free(struct block_list *bl, clr_type clrtype)
 
 			if( md->tomb_nid )
 				mvptomb_destroy(md);
-			md->~mob_data();
 			break;
 		}
 		case BL_HOM:
@@ -4106,8 +4104,6 @@ int32 unit_free(struct block_list *bl, clr_type clrtype)
 
 			skill_clear_unitgroup(bl);
 			status_change_clear(bl,1);
-
-			hd->~homun_data();
 			break;
 		}
 		case BL_MER: {
@@ -4132,8 +4128,6 @@ int32 unit_free(struct block_list *bl, clr_type clrtype)
 
 			skill_clear_unitgroup(bl);
 			status_change_clear(bl,1);
-
-			md->~s_mercenary_data();
 			break;
 		}
 		case BL_ELEM: {

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff