time@tbomb.ice.com (Tim Endres) (09/02/90)
Some time ago there was a discussion concerning code segments, and the religion regarding wether or not they should be locked down, and unpurgable, or if they should be dynamically loaded and unloaded. In the process of tightening down an application, I have realized that I am running into cases of a code segment being unloaded, with no hope of loading the thing in a full heap. When this happens, of course, things go bad. The only reasonable thing to do seems to load and lock down (after MoveHHi) all code segments (or at least those that are critical and could be called without the ability to check for their existence first). But this ties up precious memory. Does anyone have a distillation of the discussion concerning this topic? Anyone care to comment? Am I missing some obvious technique? tim. ------------------------------------------------------------- Tim Endres | time@ice.com ICE Engineering | uunet!ice.com!time 8840 Main Street | Whitmore Lake MI. 48189 | --- Disclaimed.
odawa@well.sf.ca.us (Michael Odawa) (09/04/90)
In article <b.J24QED@tbomb.ice.com> time@tbomb.ice.com writes: > > In the process of tightening down an application, I have realized > that I am running into cases of a code segment being unloaded, with > no hope of loading the thing in a full heap. When this happens, of > course, things go bad. The only reasonable thing to do seems to load > and lock down (after MoveHHi) all code segments (or at least those > that are critical and could be called without the ability to check > for their existence first). But this ties up precious memory. Thanks for bringing this up; segmentation is one of the most powerful tools you can use to minimize memory constraints, yet one which I have never seen adequately discussed. Let's use this question as an opportunity to trade some segmentation tricks. We've been using some very carefully designed segmentation schemes for several years to squeeze large programs into small memory partitions. In the course of that practice we've developed a standard approach that appears to serve us well: First, if you're using a code segment (that is, if there's any chance you'll be calling it), that segment should be moved hi and locked. The only time you should allow a code segment to be purged is when you're sure you're done with it. The key to effective segment memory management is knowing what you're calling when, and then arranging your segments in such a fashion that you can know for sure that certain routines will not be called under particular circumstances. For instance, you know there are certain routines you won't ever be using unless you are printing (that is, the functions that open & close the printer port, etc.), and yet you also know that there are certain routines you use in printing (e.g., drawing routines) that you also use whenever you update a window. So the former should be in an unloadable segment (call UnloadSeg() on it), while the latter should not be unloaded while the window's open, even though you're not printing. Similarly there are certain routines that pertain only to a particular window, or a particular menu choice, and these can be put into one or more segments that are loaded only when the window or menu choice is in use. In most of our programs, we use a scheme like the following: Segment 1: Stuff that has to be in memory always. Segment 2: Initialization Code, which we unload as we move into the MainEventLoop. Segment 3: Foreground stuff, which we can dump when we go into background. Segments 4 - n: Window or Operation-particular routines, which we can load or unload as required by what the user is doing. Another important consideration is determining which features belong in Segment 3 (that is, always loaded while in foreground) vs a later (unloadable) segment. The general idea is to structure your segments such that the user with the slowest hardware won't notice, or at worst won't mind, that you've reached for an unloaded segment. As a rule of thumb, if a menu choice entails a disk hit (e.g., "Open", "Save", "Save as...", the user won't notice you picking up a segment as well. If you still must squeeze more code out of your memory partition, you can separate out into a new segment some of the routines that pertain to menu functions that have no command-key equivalent. That is, the things that require the user to mouse around in the menu bar to find. If he has to break his train of thought to go up to the menu bar, he probably won't object to a disk hit as the function kicks in. We've found that small segments load faster than large ones (no surprise), and that the only practical upper bound to the number of segments in a program is that programmer's ability to remember which function is stashed into which segment, and to communicate this to fellow programmers. With the minimal tools that are available to help us on the Mac we have never been able to create more than a couple dozen segments in one program, but with more sophisticated tools that are available on some (more memory-constrained) platforms, we have implemented programs with 50 - 80 segments. As I said, these are some rules of thumb we have developed over the years. Does anybody know some other tricks for code segmentation? Michael Odawa Simple Software odawa@well.sf.ca.us