[comp.sys.amiga.programmer] Two questions about memory allocation

zerkle@iris.ucdavis.edu (Dan Zerkle) (01/10/91)

I recently wrote a vector graphics package that had to allocate and
de-allocate huge amounts of small structures with malloc.  I noticed
that it seemed to be running awfully slowly for some reason.  When I
wrote my own memory manager instead, the program ran three times
faster.  People running similar stuff on Unix (for the same class)
noticed that their programs didn't spend a lot of time on memory
management (according to the profiler).

So:  Why does the Amiga spend so much time fooling around with memory
management?  Is the behavior I noted typical?

Also, this same program's memory manager would allocate a large chunk
of memory at the beginning of the program (and in the middle,
actually), but I never bothered to de-allocate the memory before
exiting.  I never noticed any problems with this, and the status line
showed as much memory before execution as after.  That doesn't mean
that there wasn't a potential for problems.  Does anybody know about
this?  Was I doing a bad thing?  Should I explicitly de-allocate the
memory before exiting, or just count on "the system" to take care of
it?

If it matters:  A3000 under 2.02, Aztec C 5.0d.

           Dan Zerkle  zerkle@iris.eecs.ucdavis.edu  (916) 754-0240
           Amiga...  Because life is too short for boring computers.

mwm@raven.relay.pa.dec.com (Mike (My Watch Has Windows) Meyer) (01/10/91)

In article <8135@ucdavis.ucdavis.edu> zerkle@iris.ucdavis.edu (Dan Zerkle) writes:

   I recently wrote a vector graphics package that had to allocate and
   de-allocate huge amounts of small structures with malloc.  I noticed
   that it seemed to be running awfully slowly for some reason.  When I
   wrote my own memory manager instead, the program ran three times
   faster.  People running similar stuff on Unix (for the same class)
   noticed that their programs didn't spend a lot of time on memory
   management (according to the profiler).

   So:  Why does the Amiga spend so much time fooling around with memory
   management?  Is the behavior I noted typical?

The key is noticing that you're using Manx, not Lattice. Manx
malloc/free goes to the system (AllocMem/FreeMem), which have to deal
with linked lists of all the memory in the system. The Unix
malloc/free (and presumably, your code) allocate large chunks of
memory, and most malloc/free calls don't go to the exec. The libraries
have a simpler problem than the Amiga exec, and so tend to run
noticably faster.

   Also, this same program's memory manager would allocate a large chunk
   of memory at the beginning of the program (and in the middle,
   actually), but I never bothered to de-allocate the memory before
   exiting.  I never noticed any problems with this, and the status line
   showed as much memory before execution as after.  That doesn't mean
   that there wasn't a potential for problems.  Does anybody know about
   this?  Was I doing a bad thing?  Should I explicitly de-allocate the
   memory before exiting, or just count on "the system" to take care of
   it?

The system isn't taking care of it; the library is. The exit code from
the compiler will make sure any hanging malloc's get dealt with. This
is SOP, and you shouldn't worry about it. Some will argue that it's
better style to deallocate the memory yourself, but either way is
safe.

   If it matters:  A3000 under 2.02, Aztec C 5.0d.

Yes, it matter. Lattice does things the way Unix does - by allocating
large chunks, and using those. While testing this, I saw as much as an
order of magnitude more speed from Lattices's malloc/free than from
AllocMem/FreeMem. Manx malloc/free adds a layer around the
AllocMem/FreeMem, and so can be expected to run slower than
AllocMem/FreeMem. The advantage of Manx's way of doing things is that
free()'ed memory is given back to the system, whereas Lattice will
hang on to it until the program terminates. This causes problems in
some situations.

	<mike
--

giguere@csg.uwaterloo.ca (Eric Giguere) (01/10/91)

Routines like "malloc" and "free" are not Amiga-specific routines.  These
routines are provided by the C library you're linking to.  They eventually
call the Amiga routines AllocMem and FreeMem to get and free the memory,
but also keep track of the memory your program is using (something which
AllocMem/FreeMem won't do) and make sure all the memory is returned to
the system when your program exits.

If you're concerned about efficiency, you should use the low-level AllocMem
call.  However, you'll have to make sure that your program returns every
single piece of memory it allocates!  (AllocMem is also useful if you need
to explicitly get CHIP memory.)

If you're allocating and deallocating a lot of small items repeatedly,
it might be worth it to allocate one large chunk of memory at the beginning
of your program and do the assignments within that chunk yourself.  Also,
Intuition has an AllocRemember function to help with that kind of activity.

--
Eric Giguere                                       giguere@csg.UWaterloo.CA
           Quoth the raven: "Eat my shorts!" --- Poe & Groening

cunniff@hpfcso.HP.COM (Ross Cunniff) (01/11/91)

In article <MWM.91Jan9150459@raven.relay.pa.dec.com> mwm@raven.relay.pa.dec.com
(Mike (My Watch Has Windows) Meyer) says:

> Yes, it matter. Lattice does things the way Unix does - by allocating
> large chunks, and using those. While testing this, I saw as much as an
> order of magnitude more speed from Lattices's malloc/free than from
> AllocMem/FreeMem. Manx malloc/free adds a layer around the
> AllocMem/FreeMem, and so can be expected to run slower than
> AllocMem/FreeMem. The advantage of Manx's way of doing things is that
> free()'ed memory is given back to the system, whereas Lattice will
> hang on to it until the program terminates. This causes problems in
> some situations.

It was for this reason that I wrote my own version of malloc(), free(),
and realloc() that got fairly large (multiples of 2K?  I forget) buffers
via AllocMem(), handed pieces out to satisfy malloc() requests, and when
all of the pieces in the chunk were free()d returned the memory to the
OS via FreeMem().  This was FASTER than the standard Lattice malloc(),
free(), and realloc(); however, it doesn't satisfy the Un*x requirement
that free()d blocks be accessible until the next malloc(); i.e.  UN*X
allows the following:

	for( ptr = head; ptr; ptr = ptr->next )
		free( ptr );

which looks at ptr->next AFTER ptr has been free()d; a real no-no if you
have returned the memory to the OS.  Of course, being the nice guy that
I am, I don't do this :-)  If Manx indeed does things the way you describe,
a fair amount of ported UN*X code may show nasty, hard-to-find bugs.

As I recall, the original K&R C book has an example of a malloc/free/realloc
package that you could modify as I described above.

>	<mike

				Ross Cunniff
				Hewlett-Packard Colorado Language Lab
				cunniff@hpfcla.HP.COM

mykes@zorch.SF-Bay.ORG (Mike Schwartz) (01/11/91)

In article <8135@ucdavis.ucdavis.edu> zerkle@iris.ucdavis.edu (Dan Zerkle) writes:
>I recently wrote a vector graphics package that had to allocate and
>de-allocate huge amounts of small structures with malloc.  I noticed
>that it seemed to be running awfully slowly for some reason.  When I
>wrote my own memory manager instead, the program ran three times
>faster.  People running similar stuff on Unix (for the same class)
>noticed that their programs didn't spend a lot of time on memory
>management (according to the profiler).
>
>So:  Why does the Amiga spend so much time fooling around with memory
>management?  Is the behavior I noted typical?
>
>Also, this same program's memory manager would allocate a large chunk
>of memory at the beginning of the program (and in the middle,
>actually), but I never bothered to de-allocate the memory before
>exiting.  I never noticed any problems with this, and the status line
>showed as much memory before execution as after.  That doesn't mean
>that there wasn't a potential for problems.  Does anybody know about
>this?  Was I doing a bad thing?  Should I explicitly de-allocate the
>memory before exiting, or just count on "the system" to take care of
>it?
>
>If it matters:  A3000 under 2.02, Aztec C 5.0d.
>
>           Dan Zerkle  zerkle@iris.eecs.ucdavis.edu  (916) 754-0240
>           Amiga...  Because life is too short for boring computers.

I can't answer the first question, but if there are a lot of "little"
allocated chunks of memory, your program is certainly spending a lot of
CPU time calling free().  Under Manx, the malloc() and free() routines
are their own "glue" routines wrapped around the Amiga memory manager.  One
feature of these, as well as all the other routines that look like the ones
on Unix, is that the exit() routine in the Manx library is smart enough to 
clean up for you when you exit.  This means you can exit() with memory
allocated, files openned, etc., and exit() will clean up for you.  On the
other hand, if you call AllocMem() or Open(), YOU will have to clean up or
you WILL see a memory leak (less memory available after you run and exit).

Cheers

Mykes