Oyvind Roa (oyvind.roa++at++ks-t.no)
Thu, 14 May 1998 12:55:03 +0200
My problem is that the application slowly consumes more
and more memory, until the shared arena goes full.
I have been able to isolate the problem down to a small
test program (attached), actually using "pftown.pfb"
to simulate my real terrain tiles. The symthoms are the
same for my real tiles and "pftown.pfb".
I expect that there is something which is not allocated
shared in the loader (using the standard .pfb loader) which
is not freed when I remove the tile, or is it due to memory
fragmentation of the arena.
Does some of you know immediately what my problem is, or
alternatively how should I proceed to find out where the
memory goes ?
Environment :
Workstation : 8 cpu Onys2 InfiniteReality, 2 pipes
OpSys : IRIX6.4
Software : ProDev7.2
Performer2.2
Test program :
-----------------------
#include <stdlib.h>
#include <strings.h>
#include <Performer/pf.h>
#include <Performer/pfdu.h>
#include <Performer/pfutil.h>
#include <stdio.h>
#include <math.h>
/* Function prototypes */
void updateDBase(void *data);
void windowSetup(char *title);
void channelSetup(void);
void handleEvents(void);
/* Type declarations */
typedef struct {
pfGroup *group;
} SharedData;
/* Global variables */
SharedData *shared = NULL ;
pfChannel *chan = NULL ;
pfScene *scene = NULL ;
int exitFlag = 0;
int main(int argc, char *argv[])
{
void *arena ;
pfLightSource *light;
/* Set the shared arena size to approx. 100MByte
to get an overflow earlier than with the default
one. The program runs out of shared memory
after approx. 90 loads */
pfSharedArenaSize(100000000L) ;
pfInit() ;
pfuInitUtil() ;
arena = pfGetSharedArena();
shared = (SharedData *)pfMalloc(sizeof(SharedData), arena);
/* Configure the database paging to run in an async. subprocess */
pfMultiprocess(PFMP_APP_CULL_DRAW | PFMP_FORK_DBASE);
pfdInitConverter("pfb") ;
/* Forks CULL and DRAW and DBase */
pfConfig() ;
/* Create a X-window, and associate it with pipe 0 */
windowSetup(argv[0]);
/* Creat a scene */
scene = pfNewScene() ;
/* Add a light source to the scene */
light = pfNewLSource();
pfAddChild(scene, light);
/* Hook all the tiles in under a top group node */
shared->group = pfNewGroup();
pfAddChild(scene, shared->group);
/* Create an setup a channel */
channelSetup();
/* Register DBase callback */
pfDBaseFunc(updateDBase);
/* Set framerate to 30Hz */
pfFrameRate(30.0f) ;
pfPhase(PFPHASE_LIMIT) ;
while( !exitFlag) {
pfSync() ;
pfFrame() ;
}
pfuExitUtil() ;
pfExit() ;
exit(0) ;
}
/* Max number generated by rand() (2^16 - 1) */
#define MAX_RAND 32767.0
/* Max number of tiles simultanously loaded */
#define MAX_TILES 9
/* updateDBase() is called async. by pfFrame()
in the forked DBase process. */
void updateDBase(void *data)
{
extern SharedData *shared;
static pfNode *Tiles[MAX_TILES] ;
static pfBuffer *buf = NULL;
static int nLoads = 0 ;
static int nLoaded= 0 ;
int num ;
if (!buf) {
/* Clear the Tiles array */
bzero(Tiles, sizeof(pfNode *)*MAX_TILES) ;
/* Create and select a new pfBuffer to work with. */
buf = pfNewBuffer();
pfSelectBuffer(buf);
/* Set the PFFILEPATH */
pfFilePath(".:./pftexture");
}
/* Generate a random number from 0 to MAX_TILES-1 */
num = (int)(((float)rand() / MAX_RAND) *
((float)MAX_TILES - 0.00001)) ;
/* Check if the randomly selected tile is already loaded */
if (Tiles[num]) {
/* Remove the scenegraph subtree representing this tile */
pfBufferRemoveChild(shared->group, Tiles[num]);
pfAsyncDelete(Tiles[num]);
Tiles[num] = NULL ;
printf("Removed tile %d\n", num) ;
/* Decrement how many tiles currently loaded. */
nLoaded-- ;
} else {
/* Load a new instance of the town, and put it into the
scenegraph under the selected tile number. */
Tiles[num] = pfdLoadFile("town.pfb") ;
pfBufferAddChild(shared->group, Tiles[num]);
printf("Loaded tile %d\n", num) ;
/* Increment number of loads done. */
nLoads++ ;
/* Increment how many tiles currently loaded. */
nLoaded++ ;
}
printf("Number of loads ==> %d\n", nLoads) ;
printf("Number of tiles loaded ==> %d\n", nLoaded) ;
/* Merge the newly loaded tile (if any) into the scene. */
pfMergeBuffer();
/* Carry out the asynchronous deletion requests if any pending */
pfDBase();
}
void windowSetup(char *title)
{
pfPipe *pipe;
pfPipeWindow *win;
pipe = pfGetPipe(0);
win = pfNewPWin(pipe);
pfPWinName(win, title);
pfPWinSize(win, 1000, 1000);
pfPWinType(win, PFPWIN_TYPE_X) ;
pfuInitInput(win, PFUINPUT_X) ;
pfOpenPWin(win);
}
void channelSetup()
{
extern pfChannel *chan ;
pfPipe *pipe;
pfCoord view;
pipe = pfGetPipe(0);
chan = pfNewChan(pipe);
pfChanScene(chan, scene);
pfChanNearFar(chan, 1.0f, 5000.0f) ;
pfChanFOV(chan, 60.0f, -1.0f) ;
/* Position the channel where it is known to
see part of the loaded database */
pfSetVec3(view.hpr, 0.0f, -20.0f, 0.0f);
pfSetVec3(view.xyz, 3000.0f, 3000.0f, 50.0f);
pfChanView(chan, view.xyz, view.hpr) ;
}
-----------------------
Oyvind Roa
Senior Software Engineer
Kongsberg Defence & Aerospace A/S Phone: (+47) 32723253
P.O. Box 1003 Fax: (+47) 32286902
N-3601 Kongsberg Email: oyvind.roa++at++kongsberg.com
Norway
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
Submissions: info-performer++at++sgi.com
Admin. requests: info-performer-request++at++sgi.com
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:57:24 PDT