- Merged Shinryo's patch to speed up map-cache loading.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14377 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
Skotlex 2010-08-16 19:16:14 +00:00
parent f9f50d8c09
commit 1a2fd04b19
3 changed files with 85 additions and 40 deletions

View File

@ -3,6 +3,8 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2010/08/16
* Merged Shinryo's patch which speeds up map-cache loading (with a few changes, see eA forum thread #253218 for details) [Skotlex]
2010/08/14
* Rev. 14373 Quest log kill count now updated properly. (Added from topic 253813) [L0ne_W0lf]
2010/08/11

View File

@ -2331,11 +2331,9 @@ int map_random_dir(struct block_list *bl, short *x, short *y)
}
// gatŒn
static struct mapcell map_gat2cell(int gat)
inline static struct mapcell map_gat2cell(int gat)
{
struct mapcell cell;
memset(&cell, 0, sizeof(cell));
struct mapcell cell = {0};
switch( gat )
{
case 0: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // walkable ground
@ -2670,59 +2668,85 @@ int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port)
}
/*==========================================
* Map cache reading
*==========================================*/
int map_readfromcache(struct map_data *m, FILE *fp)
* [Shinryo]: Init and free the mapcache
*------------------------------------------*/
char *map_init_mapcache(FILE *fp)
{
struct map_cache_main_header header;
struct map_cache_map_info info;
int i;
size_t size = 0, read_size;
char *buffer;
if( !fp )
return 0;
// No file open? Return..
nullpo_ret(fp);
// Get file size
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(&header, sizeof(struct map_cache_main_header), 1, fp);
for( i = 0; i < header.map_count; ++i )
{
fread(&info, sizeof(struct map_cache_map_info), 1, fp);
// Allocate enough space
CREATE(buffer, unsigned char, size);
if( strcmp(m->name, info.name) == 0 )
break; // Map found
// No memory? Return..
nullpo_ret(buffer);
// Map not found, jump to the beginning of the next map info header
fseek(fp, info.len, SEEK_CUR);
// Read file into buffer..
if((read_size = fread(buffer, sizeof(char), size, fp)) != size) {
ShowError("map_init_mapcache: Could not read entire mapcache file\n");
return NULL;
}
if( i < header.map_count )
{
unsigned char *buf, *buf2;
return buffer;
}
/*==========================================
* Map cache reading
* [Shinryo]: Optimized some behaviour to speed this up
*==========================================*/
int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer)
{
int i;
struct map_cache_main_header *header = (struct map_cache_main_header *)buffer;
struct map_cache_map_info *info;
unsigned char *p = buffer + sizeof(struct map_cache_main_header);
for(i = 0; i < header->map_count; i++) {
info = (struct map_cache_map_info *)p;
if( strcmp(m->name, info->name) == 0 )
break; // Map found
// Jump to next entry..
p += sizeof(struct map_cache_map_info) + info->len;
}
if( i < header->map_count ) {
unsigned long size, xy;
if( info.xs <= 0 || info.ys <= 0 )
return 0;// invalid
if( info->xs <= 0 || info->ys <= 0 )
return 0;// Invalid
m->xs = info.xs;
m->ys = info.ys;
size = (unsigned long)info.xs*(unsigned long)info.ys;
m->xs = info->xs;
m->ys = info->ys;
size = (unsigned long)info->xs*(unsigned long)info->ys;
if(size > MAX_MAP_SIZE) {
ShowWarning("map_readfromcache: %s exceeded MAX_MAP_SIZE of %d\n", info->name, MAX_MAP_SIZE);
return 0; // Say not found to remove it from list.. [Shinryo]
}
// TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo]
decode_zip(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len);
buf = (unsigned char*)aMalloc(info.len); // temp buffer to read the zipped map
buf2 = (unsigned char*)aMalloc(size); // temp buffer to unpack the data
CREATE(m->cell, struct mapcell, size);
fread(buf, info.len, 1, fp);
decode_zip(buf2, &size, buf, info.len); // Unzip the map from the buffer
for( xy = 0; xy < size; ++xy )
m->cell[xy] = map_gat2cell(buf2[xy]);
m->cell[xy] = map_gat2cell(decode_buffer[xy]);
aFree(buf);
aFree(buf2);
return 1;
}
return 0;// not found
return 0; // Not found
}
int map_addmap(char* mapname)
@ -2867,6 +2891,8 @@ int map_readallmaps (void)
int i;
FILE* fp=NULL;
int maps_removed = 0;
unsigned char *map_cache_buffer; // Has the uncompressed gat data of all maps, so just one allocation has to be made
unsigned char map_cache_decode_buffer[MAX_MAP_SIZE];
if( enable_grf )
ShowStatus("Loading maps (using GRF files)...\n");
@ -2878,20 +2904,32 @@ int map_readallmaps (void)
ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", map_cache_file);
exit(EXIT_FAILURE); //No use launching server if maps can't be read.
}
// Init mapcache data.. [Shinryo]
map_cache_buffer = map_init_mapcache(fp);
if(!map_cache_buffer) {
ShowFatalError("Failed to initialize mapcache data (%s)..\n", map_cache_file);
exit(EXIT_FAILURE);
}
}
// Mapcache reading is now fast enough, the progress info will just slow it down so don't use it anymore [Shinryo]
if(!enable_grf)
ShowStatus("Loading maps (%d)..\n", map_num);
for(i = 0; i < map_num; i++)
{
size_t size;
// show progress
if(enable_grf)
ShowStatus("Loading maps [%i/%i]: %s"CL_CLL"\r", i, map_num, map[i].name);
// try to load the map
if( !
(enable_grf?
map_readgat(&map[i])
:map_readfromcache(&map[i], fp))
:map_readfromcache(&map[i], map_cache_buffer, map_cache_decode_buffer))
) {
map_delmapid(i);
maps_removed++;
@ -2934,9 +2972,13 @@ int map_readallmaps (void)
map[i].block_mob = (struct block_list**)aCalloc(size, 1);
}
if( !enable_grf )
if( !enable_grf ) {
fclose(fp);
// The cache isn't needed anymore, so free it.. [Shinryo]
aFree(map_cache_buffer);
}
// finished map loading
ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map_num);
instance_start = map_num; // Next Map Index will be instances

View File

@ -44,6 +44,7 @@ struct item_data;
#define MAX_DROP_PER_MAP 48
#define MAX_IGNORE_LIST 20 // official is 14
#define MAX_VENDING 12
#define MAX_MAP_SIZE 512*512 // Wasn't there something like this already? Can't find it.. [Shinryo]
#define MOBID_EMPERIUM 1288
// Added definitions for WoESE objects. [L0ne_W0lf]
#define MOBID_BARRICADE1 1905