Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!apple!lsr From: lsr@Apple.COM (Larry Rosenstein) Newsgroups: comp.sys.mac.programmer Subject: Re: Large Programs and Memory Management Questions Message-ID: <13309@goofy.Apple.COM> Date: 3 May 91 02:27:53 GMT References: <1991Apr24.122618.13791@bmers95.bnr.ca> Organization: Apple Computer, Inc. Lines: 86 In article <1991Apr24.122618.13791@bmers95.bnr.ca> slang@bmerh563.bnr.ca (Steven Langlois) writes: >What is the best method for unloading segments? In MacApp we unload non-resident segments after each event. (The routine to do this can be called at any time, if you're careful.) Resident segment is a MacApp concept. In the simplest case, the app includes a resource listing the names of the resident segments. You can also mark segments as resident programmatically. >There is the "unload all your segments every time through your event loop" >method but is this an effective method or are there other better methods? Some people have proposed trying to figure out if a segment is being used by tracing down the call stack, but I'm not sure if this is any better. (I think the idea was to do this when you needed extra memory.) Unloading a segment doesn't purge it from memory; it simply marks the jump table entries as unloaded, and allows the segment to float in the heap. If you use it again before it gets purged, then it doesn't have to be read from disk. >From what I have read, it is typically a good idea to unload your >initialization segment before entering your main event loop. You will then You should be careful that unloading this segment doesn't create a hole in the heap because other segments were loaded after it and these weren't also unloaded. For example, you know that the main segment is loaded first and never gets unloaded. It can make a call to the initialization code, which will load various segments. Before starting the main event loop, you can unloaded all segments except the main segment, in order to start with a clean slate. It help to check the state of your heap at various times to make sure that there are no free block surrounded by locked code segments. >compact the heap or wait until a call to the memory manager does it for >you? It should never be necessary to call explicitly compact the heap, if there are no non-relocatable or locked blocks in the middle of the heap. You also have to be careful about a very large relocatable block that's bigger than any free space, because it is essentially locked and can't be moved. >What would happen if there was not enough memory to load a CODE segment? You get a system error. The same is true of failing to load other resources like defprocs, packages, ... >more importantly, how do you prevent this from happening, especially when As someone said you need to keep a reserve handle around that you can free if necessary. The Memory Manager allows you to install a grow zone proc that will be called if it needs more memory. You can release the handle in your grow zone. MacApp does essentially this except that we try to be clever about the size of this handle so that it doesn't take up memory needlessly. The concept is that your application needs X bytes of space for the maximum amount of code, defprocs, ... you use at any point in time. To prevent a crash, you have to make sure that you have this amount of memory available. Segments that are already in memory count towards satisfying this requirement. So the reserve handle size can be reduced by the total sizes of in-memory code segments. Another subtle point is that you only need to guarantee this reserve memory before you make a non-segment request. (In MacApp we call this a permanent request, because the memory is permanently allocated in the document, and can't be freed unless the user deletes something.) MacApp maintains a flag that indicates whether the program is in permanent or temporary request mode. When the flag is changed from temporary to permanent we make sure that the reserve handle is allocated properly. The grow zone proc also uses the flag to decide if the reserve should be freed. This scheme works very well as long as you tell MacApp the maximum amount of loaded code, defprocs, ... you need. The MacApp debugger has tools that help to figure this out, and the sizes are specified in resources. And you still need to check whether permanent allocations succeed, and gracefully back out if not. -- Larry Rosenstein, Apple Computer, Inc. lsr@apple.com (or AppleLink: Rosenstein1)