Scrap some memory and somehow avoid heap fragmentation

This commit is contained in:
Lephenixnoir 2021-08-31 19:18:55 +02:00
parent 530355e36c
commit 1f290006f1
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
11 changed files with 130 additions and 58 deletions

View File

@ -378,18 +378,13 @@ static FileMapping gWADMap;
/* Index of most likely sectors for fragment search. (CGDOOM_WAD_MMAP) */
static SectorIndexInfo *gIndex = NULL;
/* Developer statistics */
static int gDevFragments = 0;
static int gDevIndexHits = 0;
static const void *gDevLowestFragment = NULL;
int gDevUnalignedLumpLoads = 0;
int gDevUnalignedLumpSize = 0;
/* Global options */
int CGD_TrustUnalignedLumps = 0;
/* Performance counters */
struct CGD_Perf CGD_Perf;
/* Developer statistics */
struct CGD_Stats CGD_Stats;
/* Read next sector from file, while caching into a buffer. */
const void *ReadNextSector(FileAccessCache *fc, int *size)
@ -451,7 +446,7 @@ int FindSectorInFlash(const void *buf, int size)
typeof(&memcmp) memcmp_fun = &memcmp;
if(size == FLASH_PAGE_SIZE) memcmp_fun = &CGD_sector_memcmp;
gDevFragments++;
CGD_Stats.WADFragments++;
#ifdef FLASH_INDEX
/* If an index has been built, search in it */
@ -459,7 +454,7 @@ int FindSectorInFlash(const void *buf, int size)
IndexSearchSector(gIndex, buf, &lo, &hi);
for(int i = lo; i < hi; i++) {
if(!memcmp_fun(buf, gIndex[i].sector, size)) {
gDevIndexHits++;
CGD_Stats.WADIndexHits++;
return (gIndex[i].sector - FLASH_START) / FLASH_PAGE_SIZE;
}
}
@ -515,8 +510,8 @@ int CreateFileMapping(int fd, FileMapping *pMap)
/* Look for consecutive sectors in the same fragment */
const void *pFragment = FLASH_START + (iSectorID * FLASH_PAGE_SIZE);
if(!gDevLowestFragment || pFragment < gDevLowestFragment)
gDevLowestFragment = pFragment;
if(!CGD_Stats.WADLowestFragment || pFragment<CGD_Stats.WADLowestFragment)
CGD_Stats.WADLowestFragment = pFragment;
for(;;)
{
@ -701,11 +696,11 @@ int main(void)
Bdisp_AllClr_VRAM();
Layout_CenteredText(&l, "Developer info");
Layout_Spacing(&l, 12);
Layout_Text(&l, "Fragments:", "%d", gDevFragments);
Layout_Text(&l, "Index hits:", "%d (%d%%)", gDevIndexHits,
(gDevIndexHits * 100 / gDevFragments));
Layout_Text(&l, "Fragments:", "%d", CGD_Stats.WADFragments);
Layout_Text(&l, "Index hits:", "%d (%d%%)", CGD_Stats.WADIndexHits,
(CGD_Stats.WADIndexHits * 100 / CGD_Stats.WADFragments));
Layout_Text(&l, "Lowest fragment:", "%p",
gDevLowestFragment);
CGD_Stats.WADLowestFragment);
Layout_Spacing(&l, 12);
Layout_Text(&l, "Index build time:", "%d ms", ms_index);
Layout_Text(&l, "File mapping time:", "%d ms", ms_mmap);
@ -733,8 +728,20 @@ int main(void)
Bdisp_AllClr_VRAM();
Layout_CenteredText(&l, "Developer info");
Layout_Spacing(&l, 12);
Layout_Text(&l, "Unaligned lumps loaded:", "%d", gDevUnalignedLumpLoads);
Layout_Text(&l, "Unaligned size:", "%d B", gDevUnalignedLumpSize);
Layout_Text(&l, "Memory allocated:", "%d kB",
CGD_Stats.MemoryAllocated >> 10);
Layout_Spacing(&l, 12);
Layout_Text(&l, "Lumps loaded:", "%d (%d kB)",
CGD_Stats.LumpsLoaded,
(int)(CGD_Stats.LumpsLoadedTotal >> 10));
Layout_Text(&l, "... of which unaligned:", "%d (%d kB)",
CGD_Stats.UnalignedLumpsLoaded,
(int)(CGD_Stats.UnalignedLumpsLoadedTotal >> 10));
Layout_Text(&l, "Lumps referenced:", "%d (%d kB)",
CGD_Stats.LumpsReferenced,
(int)(CGD_Stats.LumpsReferencedTotal >> 10));
Bdisp_FrameAndColor(3, 16);
Bdisp_FrameAndColor(1, 0);
Bdisp_PutDisp_DD();

View File

@ -59,4 +59,28 @@ struct CGD_Perf
prof_t UnalignedLumpLoading;
};
struct CGD_Stats
{
/* Fragments in the WAD file */
int WADFragments;
/* Lowest fragment address (hints at filesystem entry point) */
void const *WADLowestFragment;
/* Number of index hits during fragment search */
int WADIndexHits;
/* Total memory allocated with Z_Malloc (bytes) */
uint32_t MemoryAllocated;
/* Number of lumps loaded, number of lumps not loaded (addressed directly in
ROM), number of unaligned lumps loaded */
int LumpsLoaded;
int LumpsReferenced;
int UnalignedLumpsLoaded;
/* The total size for these three catefories (bytes) */
uint64_t LumpsLoadedTotal;
uint64_t LumpsReferencedTotal;
uint64_t UnalignedLumpsLoadedTotal;
};
#endif /* CGDOOM_H */

View File

@ -25,8 +25,7 @@
const char* endmsg[NUM_QUITMESSAGES+1]=
{
const char * const endmsg[NUM_QUITMESSAGES+1] = {
// DOOM1
QUITMSG,
"please don't leave, there's more\ndemons to toast!",

View File

@ -46,7 +46,7 @@
// QuitDOOM messages
#define NUM_QUITMESSAGES 22
extern const char* endmsg[];
extern const char * const endmsg[];
#endif

View File

@ -54,7 +54,7 @@ const char sprnames[NUMSPRITES][5] = {
};
state_t states[NUMSTATES] = {
state_t const states[NUMSTATES] = {
{SPR_TROO,0,-1,0,S_NULL,0,0}, // S_NULL
{SPR_SHTG,4,0,TA_Light0,S_NULL,0,0}, // S_LIGHTDONE
{SPR_PUNG,0,1,TA_WeaponReady,S_PUNCH,0,0}, // S_PUNCH

View File

@ -1156,7 +1156,7 @@ typedef struct
long misc1, misc2;
} state_t;
extern state_t states[NUMSTATES];
extern state_t const states[NUMSTATES];
extern const char sprnames[NUMSPRITES][5];

View File

@ -1,18 +1,15 @@
#include "platform.h"
#define SYSTEM_STACK_SAFE (64*1024)
#define USER_STACK_SAFE (32*1024)
//CGDOOM
#define SYSTEM_STACK_SAFE (90*1024)
#define USER_STACK_SAFE (40*1024)
//memory mapping:
//0x880A2AD5..0x880CB2D5:SaveVRAMBuffer 165888 bytes
// SaveVRAMBuffer 165888 bytes
#define SAVE_VRAM_SIZE (WIDTH*HEIGHT*2-3)
extern unsigned char *SaveVRAMBuffer;//[SAVE_VRAM_SIZE];
extern unsigned char *SaveVRAMBuffer;
//0xA80F0000..0xA815FFFF: system stack (512 kB).
// system stack (512 kB).
#define SYSTEM_STACK_SIZE (512*1024-SYSTEM_STACK_SAFE)
extern unsigned char *SystemStack;//[SYSTEM_STACK_SIZE];
extern unsigned char *SystemStack;
extern unsigned short *VRAM;
void * CGDMalloc(int iSize);

View File

@ -302,7 +302,6 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash)
{
c = FindInFlash((const void **)&lumpcache[lump], lumpinfo[lump].size, lumpinfo[lump].position);
}
// else ASSERT(lumpinfo[lump].size != 10240);
int full = (c == lumpinfo[lump].size);
int aligned = (((uint32_t)lumpcache[lump] & 1) == 0);
@ -311,11 +310,10 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash)
aligned = 1;
/* Record statistics on loading unaligned but full lumps */
extern int gDevUnalignedLumpLoads;
extern int gDevUnalignedLumpSize;
extern struct CGD_Stats CGD_Stats;
if(full && !aligned) {
gDevUnalignedLumpLoads++;
gDevUnalignedLumpSize += lumpinfo[lump].size;
CGD_Stats.UnalignedLumpsLoaded++;
CGD_Stats.UnalignedLumpsLoadedTotal += lumpinfo[lump].size;
}
/* Allocate only if the lump spans several fragments, or is misaligned;
@ -323,11 +321,13 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash)
the heap would provide. */
if(!full || !aligned)
{
CGD_Stats.LumpsLoaded++;
CGD_Stats.LumpsLoadedTotal += lumpinfo[lump].size;
prof_enter(CGD_Perf.LumpLoading);
if(!aligned)
prof_enter(CGD_Perf.UnalignedLumpLoading);
Z_Malloc (lumpinfo[lump].size, tag, &lumpcache[lump]);
W_ReadLump (lump, lumpcache[lump]);
@ -335,6 +335,11 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash)
prof_leave(CGD_Perf.UnalignedLumpLoading);
prof_leave(CGD_Perf.LumpLoading);
}
else
{
CGD_Stats.LumpsReferenced++;
CGD_Stats.LumpsReferencedTotal += lumpinfo[lump].size;
}
return lumpcache[lump];
}
@ -345,29 +350,20 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash)
//
static void* W_CacheLumpNumCommon( int lump, int tag,int iEnableFlash)
{
if (lump >= numlumps)
{
I_Error ("W_CacheLumpNum: %i >= numlumps (%i)",lump,numlumps);
}
//printf("x");
if (!lumpcache[lump])
{
// try to find in flash (may fail if the piece is in 2 fragments (file fragmentaion)
W_ReadLumpWithZ_Malloc(lump,tag,iEnableFlash);
}
else
{
//printf ("cache hit on lump %i\n",lump);
Z_ChangeTag (lumpcache[lump],tag);
}
/*if (lump==1203)
printf("sky access, returning %x \n",lumpcache[lump]);*/
if(lumpcache[lump] == NULL)
I_ErrorI("W_CacheLumpNumCommon", (int)lumpcache[lump], lump, 0, 0);

View File

@ -51,7 +51,7 @@ typedef struct
memblock_t* rover;
} memzone_t;
/* CGDOOM: In order to increase available memory, we need to support multiple
/* CGDoom: In order to increase available memory, we need to support multiple
zones. The code below is adapted to do that:
* Z_ClearZone is already parameterized, nothing to do (it's never called)
@ -64,13 +64,16 @@ typedef struct
* Z_FreeMemory is changed to iterate on one or all zones
In addition to that, the next-fit strategy with a rover also runs over zones
since starting at the first zone when it's full loses *a lot* of time. */
static memzone_t *zones[ZONE_MAX];
static int zone_count;
since starting at the first zone when it's full loses *a lot* of time.
However, the next-fit strategy tends to produce *a lot* of fragmentation,
resulting in early allocation failures due to the lack of large spaces. For
this reason, the last region is not part of the zone rover rotation. */
static memzone_t *zones[ZONE_MAX]; /* static memzone_t *mainzone; */
static int zone_count;
static int zone_rover = 0;
// static memzone_t* mainzone;
//
@ -225,6 +228,7 @@ void Z_Free (const void* ptr)
void* Z_Malloc( int size, int tag, void* user )
{
prof_enter(CGD_Perf.DynamicAllocation);
CGD_Stats.MemoryAllocated += size;
static int iCalled = 0;
int extra;
@ -308,15 +312,22 @@ void* Z_Malloc( int size, int tag, void* user )
if (failed)
{
zone_no++;
if(zone_no == zone_count)
zone_no = 0;
if(zone_no == zone_start)
if (zone_no == zone_count - 1)
{
I_ErrorI ("Z_Malloc failure", size, 0, 0, 0);
prof_leave(CGD_Perf.DynamicAllocation);
return NULL;
}
/* When rotating, perform a full cycle before defaulting to the last
zone; this preserves the last zone to avoid fragmentation and absorb
occasional large chunks */
zone_no++;
if(zone_no == zone_count - 1)
zone_no = 0;
if(zone_no == zone_start)
zone_no = zone_count - 1;
zone = zones[zone_no];
}
else break;
@ -362,7 +373,8 @@ void* Z_Malloc( int size, int tag, void* user )
// next allocation will start looking here
zone->rover = base->next;
zone_rover = zone_no;
if (zone_no != zone_count - 1)
zone_rover = zone_no;
base->id = ZONEID;
@ -500,3 +512,37 @@ int Z_FreeMemory (int zone)
return free;
}
//
// Z_LargestFreeBlock
//
int Z_LargestFreeBlock (int zone)
{
if (zone < 0)
{
int maxsize = 0;
for (int i = 0; i < zone_count; i++) {
int n = Z_LargestFreeBlock(i);
if (n > maxsize)
maxsize = n;
}
return maxsize;
}
memblock_t* block;
int maxsize = 0;
memzone_t* mainzone = zones[zone];
for(block = mainzone->blocklist.next;block != &mainzone->blocklist;block = block->next)
{
if (!block->user || block->tag >= PU_PURGELEVEL)
{
if (block->size > maxsize)
maxsize = block->size;
}
}
return maxsize;
}

View File

@ -53,10 +53,12 @@ void Z_DumpHeap (int lowtag, int hightag);
void Z_CheckHeap (void);
void Z_ChangeTag2 (const void *ptr, int tag);
/* CGDOOM: Returns free memory in specified zone, or all zones if zone < 0 */
/* CGDoom: Returns free memory in specified zone, or all zones if zone < 0 */
int Z_FreeMemory (int zone);
/* CGDoom: Returns largest free block in specified zone, or all if zone < 0 */
int Z_LargestFreeBlock (int zone);
/* CGDOOM: Support for multiple zones is added; Z_Init() now does nothing,
/* CGDoom: Support for multiple zones is added; Z_Init() now does nothing,
zones need to be added manually (see D_DoomMain()). */
void Z_AddZone (void *zone, int size);

View File

@ -80,6 +80,7 @@ extern int CGD_TrustUnalignedLumps;
#endif
extern struct CGD_Perf CGD_Perf;
extern struct CGD_Stats CGD_Stats;
//---