[comp.sys.mac.programmer] WANTED: Discussions regarding code segment loading

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