From e7ff8af6e8b49f89d96621a630dfc2500165c608 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 17 Aug 2012 20:59:50 +0000 Subject: Follow up r16656 improved unloadnpcfile stuff performance-wise, making npcs from the same file share the filepath reference rather than each having its own copy. Special Ultra Super Thanks to Trojal <3 git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16657 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/npc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 13 deletions(-) (limited to 'src/map/npc.c') diff --git a/src/map/npc.c b/src/map/npc.c index e8ebb3180..d5c7c021a 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -82,6 +82,17 @@ struct event_data { static struct eri *timer_event_ers; //For the npc timer data. [Skotlex] +/* hello */ +static char *npc_last_path; +static char *npc_last_ref; + +struct npc_path_data { + char* path; + unsigned short references; +}; +struct npc_path_data *npc_last_npd; +static DBMap *npc_path_db; + //For holding the view data of npc classes. [Skotlex] static struct view_data npc_viewdb[MAX_NPC_CLASS]; @@ -1749,8 +1760,17 @@ int npc_unload(struct npc_data* nd, bool single) { npc_chat_finalize(nd); // deallocate npc PCRE data structures #endif - if( nd->path ) - aFree(nd->path); + if( single && nd->path ) { + struct npc_path_data* npd = NULL; + if( nd->path && nd->path != npc_last_ref ) { + npd = strdb_get(npc_path_db, nd->path); + } + + if( npd && --npd->references == 0 ) { + strdb_remove(npc_path_db, nd->path);/* remove from db */ + aFree(nd->path);/* remove now that no other instances exist */ + } + } if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] aFree(nd->u.shop.shop_item); @@ -1927,12 +1947,10 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta char other_mapname[32]; int i = 0; - do - { + do { ++i; snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y); - } - while( npc_name2id(newname) != NULL ); + } while( npc_name2id(newname) != NULL ); strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map[nd->bl.m].index))); strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map[dnd->bl.m].index))); @@ -1943,8 +1961,30 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta safestrncpy(nd->exname, newname, sizeof(nd->exname)); } - CREATE(nd->path, char, strlen(filepath)+1); - safestrncpy(nd->path, filepath, strlen(filepath)+1); + if( npc_last_path != filepath ) { + struct npc_path_data * npd = NULL; + + if( !(npd = strdb_get(npc_path_db,filepath) ) ) { + CREATE(npd, struct npc_path_data, 1); + strdb_put(npc_path_db, filepath, npd); + + CREATE(npd->path, char, strlen(filepath)+1); + safestrncpy(npd->path, filepath, strlen(filepath)+1); + + npd->references = 1; + } + + nd->path = npd->path; + npd->references++; + + npc_last_npd = npd; + npc_last_ref = npd->path; + npc_last_path = (char*) filepath; + } else { + nd->path = npc_last_ref; + if( npc_last_npd ) + npc_last_npd->references++; + } } struct npc_data* npc_add_warp(short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) @@ -3498,7 +3538,19 @@ void npc_read_event_script(void) ShowInfo("%s: %d '%s' events.\n", config[i].name, script_event[i].event_count, config[i].event_name); } } - +void npc_clear_pathlist(void) { + struct npc_path_data *npd = NULL; + DBIterator *path_list = db_iterator(npc_path_db); + + + /* free all npc_path_data filepaths */ + for( npd = dbi_first(path_list); dbi_exists(path_list); npd = dbi_next(path_list) ) { + if( npd->path ) + aFree(npd->path); + } + + dbi_destroy(path_list); +} int npc_reload(void) { struct npc_src_list *nsl; int m, i; @@ -3506,9 +3558,13 @@ int npc_reload(void) { struct s_mapiterator* iter; struct block_list* bl; + npc_clear_pathlist(); + + db_clear(npc_path_db); + db_clear(npcname_db); db_clear(ev_db); - + //Remove all npcs/mobs. [Skotlex] iter = mapit_geteachiddb(); @@ -3610,9 +3666,10 @@ void do_clear_npc(void) { * I *------------------------------------------*/ int do_final_npc(void) { - + npc_clear_pathlist(); ev_db->destroy(ev_db, NULL); npcname_db->destroy(npcname_db, NULL); + npc_path_db->destroy(npc_path_db, NULL); ers_destroy(timer_event_ers); npc_clearsrcfile(); @@ -3669,7 +3726,8 @@ int do_init_npc(void) ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1); npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH); - + npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80); + timer_event_ers = ers_new(sizeof(struct timer_event_data)); // process all npc files @@ -3715,6 +3773,6 @@ int do_init_npc(void) fake_nd->u.scr.timerid = INVALID_TIMER; map_addiddb(&fake_nd->bl); // End of initialization - + return 0; } -- cgit v1.2.3-60-g2f50