[comp.sys.amiga.programmer] Memory fragging

mike@zorch.SF-Bay.ORG (Mike Smithwick) (05/22/91)

[Attack of the killer poodles!]

I am using loads of chip ram and it seems to be fragging pretty badly. So much
so that I can't run the program more than a couple of times without having
to reboot. I am not running any other programs at the same time so there is  
no outside interference. Theoretically I should return to the same state
as I had before, I am not.

Any ideas?


mike




-- 
"There is no problem to big that can't be solved with high explosives"-Rush

Mike Smithwick - ames!zorch!mike

peter@cbmvax.commodore.com (Peter Cherna) (05/23/91)

In article <1991May21.195251.16477@zorch.SF-Bay.ORG> mike@zorch.SF-Bay.ORG (Mike Smithwick) writes:
>[Attack of the killer poodles!]
>
>I am using loads of chip ram and it seems to be fragging pretty badly. So much
>so that I can't run the program more than a couple of times without having
>to reboot. I am not running any other programs at the same time so there is  
>no outside interference. Theoretically I should return to the same state
>as I had before, I am not.

Do as much as you can to free your resources in the reverse order that
you obtained them in.  Avoid using FreeRemember(FALSE).  Avoid
doing Alloc(A);Alloc(B);Alloc(C),  ... , Free(B).

If you do lots of allocations and frees of a fixed size, try to
code up some kind of pool allocation scheme.

Make sure you free all your resources.

>mike

     Peter
--
Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc.
{uunet|rutgers}!cbmvax!peter    peter@cbmvax.commodore.com
My opinions do not necessarily represent the opinions of my employer.
"If all you have is a hammer, everything looks like a nail."

dillon@overload.Berkeley.CA.US (Matthew Dillon) (05/23/91)

In article <1991May21.195251.16477@zorch.SF-Bay.ORG> mike@zorch.SF-Bay.ORG (Mike Smithwick) writes:
>[Attack of the killer poodles!]
>
>I am using loads of chip ram and it seems to be fragging pretty badly. So much
>so that I can't run the program more than a couple of times without having
>to reboot. I am not running any other programs at the same time so there is
>no outside interference. Theoretically I should return to the same state
>as I had before, I am not.
>
>Any ideas?
>
>mike
>--
>"There is no problem to big that can't be solved with high explosives"-Rush
>
>Mike Smithwick - ames!zorch!mike

    You are absolutely right.  If you return all resources and free all
    memory (that you allocated :-)) you should wind up in basically the
    original state as far as memory fragmentation goes.

    Two common problems:

    (1) your program has side effects, such as creating RAM: files,
	that leaves memory fragmented.

    (2) you are not FreeMem()ing all the memory you allocated --- easiest
	to simply run

	1> Avail

	After each program run (keep in mind that the first time the program
	is run might have side effects re: external libraries it may open
	which stick around).

	Avail should return the same amount of memory free.

				    -Matt

--

    Matthew Dillon	    dillon@Overload.Berkeley.CA.US
    891 Regal Rd.	    uunet.uu.net!overload!dillon
    Berkeley, Ca. 94708
    USA

jseymour@medar.com (James Seymour) (05/23/91)

In article <21795@cbmvax.commodore.com> peter@cbmvax.commodore.com (Peter Cherna) writes:
:In article <1991May21.195251.16477@zorch.SF-Bay.ORG> mike@zorch.SF-Bay.ORG (Mike Smithwick) writes:
::[Attack of the killer poodles!]
::
::I am using loads of chip ram and it seems to be fragging pretty badly. So much
::so that I can't run the program more than a couple of times without having
::to reboot. I am not running any other programs at the same time so there is  
::no outside interference. Theoretically I should return to the same state
::as I had before, I am not.
:
:Do as much as you can to free your resources in the reverse order that
:you obtained them in.  Avoid using FreeRemember(FALSE).  Avoid
:doing Alloc(A);Alloc(B);Alloc(C),  ... , Free(B).
:

But if you eventually F/free() the other two, the three chunks of memory
(in the above example) will be coalesced by the o/s, won't they?  (Assuming
no intervening allocations that haven't been free'd.)  In other words,
if I run multiple processes, each doing any number of memory allocs in any
order, providing they all properly free the memory before terminating,
AmigaDOS will coalesce all of the adjacent free'd spaces won't it?  May
sound like a stupid question, but the way Peter phrased his answer, I had
to ask.  [I'd RTFM, but it hasn't been published/released yet :-)]

:
:     Peter
:--
:"If all you have is a hammer, everything looks like a nail."

Every time I see this .sig line, I think of the poor souls that think
Windows (tm) is representative of what the rest of us mean by multi-tasking.

-- 
Jim Seymour				| Medar, Inc.
...!uunet!medar!jseymour		| 38700 Grand River Ave.
jseymour@medar.com			| Farmington Hills, MI. 48331
CIS: 72730,1166  GEnie: jseymour	| FAX: (313)477-8897

peter@cbmvax.commodore.com (Peter Cherna) (05/23/91)

In article <1991May23.114423.11039@medar.com> jseymour@medar.com (James Seymour) writes:
>But if you eventually F/free() the other two, the three chunks of memory
>(in the above example) will be coalesced by the o/s, won't they?

I'm not a fragging expert, but I've always assumed the system was
happier if you tried to free things in reverse order.  (Intervening
processes may make allocations.)  It's also a generally good programming
practice.

>Jim Seymour				| Medar, Inc.

     Peter
--
Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc.
{uunet|rutgers}!cbmvax!peter    peter@cbmvax.commodore.com
My opinions do not necessarily represent the opinions of my employer.
"If all you have is a hammer, everything looks like a nail."

dillon@overload.Berkeley.CA.US (Matthew Dillon) (05/24/91)

In article <21795@cbmvax.commodore.com> peter@cbmvax.commodore.com (Peter Cherna) writes:
>In article <1991May21.195251.16477@zorch.SF-Bay.ORG> mike@zorch.SF-Bay.ORG (Mike Smithwick) writes:
>...
>
>Do as much as you can to free your resources in the reverse order that
>you obtained them in.	Avoid using FreeRemember(FALSE).  Avoid
>doing Alloc(A);Alloc(B);Alloc(C),  ... , Free(B).

    Why?  What's wrong with Alloc(A) Alloc(B) Alloc(C) .. Free(B) Free(A)
    Free(C) ?

				-Matt

>>mike
>
>     Peter
>--
>Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc.
>{uunet|rutgers}!cbmvax!peter	 peter@cbmvax.commodore.com
>My opinions do not necessarily represent the opinions of my employer.
>"If all you have is a hammer, everything looks like a nail."

--

    Matthew Dillon	    dillon@Overload.Berkeley.CA.US
    891 Regal Rd.	    uunet.uu.net!overload!dillon
    Berkeley, Ca. 94708
    USA

efb@dvncnms.Devoncnms.Unisys.COM (Edward Bacon) (05/24/91)

In article <21795@cbmvax.commodore.com> peter@cbmvax.commodore.com (Peter Cherna) writes:
>In article <1991May21.195251.16477@zorch.SF-Bay.ORG> mike@zorch.SF-Bay.ORG (Mike Smithwick) writes:
>>[Attack of the killer poodles!]
>>
>>I am using loads of chip ram and it seems to be fragging pretty badly. So much
> [ ... ]


>Do as much as you can to free your resources in the reverse order that
>you obtained them in.  Avoid using FreeRemember(FALSE).  Avoid
>doing Alloc(A);Alloc(B);Alloc(C),  ... , Free(B).
>

How about lists of Gadgets?  Here is what I do:
One routine uses AllocRemember() for the gadget, text and image memory.
It calls FreeRemember(TRUE) or FreeRemember(FALSE), if every thing went
OK or not (oops I think I just got that backwards ..).  When I go to
destroy a window I call a routine that starts with the FirstGadget
frees it (and associated text or image) memory and then does the NextGadget.
Is this cool or in violation of what you advocated?  I am sortta allocating
chunks of memory for the gadget and then freeing the chunks, but all of
the window's gadget memory chunks get freed in reverse order.

What is the problem with FreeRemember(FALSE) ?

peter@cbmvax.commodore.com (Peter Cherna) (05/24/91)

In article <886@dvncnms.Devoncnms.Unisys.COM> efb@dvncnms.Devoncnms.Unisys.COM (Edward Bacon) writes:
>How about lists of Gadgets?  Here is what I do:
>One routine uses AllocRemember() for the gadget, text and image memory.
>It calls FreeRemember(TRUE) or FreeRemember(FALSE),

AllocRemember() does:

	AllocMem( a little header )
	AllocMem( the block you want )

and then puts tracking information into the little header.  FreeRemember(TRUE)
disposes of the headers and the blocks.  FreeRemember(FALSE) blows away
all the little headers, and leaves you with a memory map that looks like


     *----*----*----*----*----*----*----*----*----*----

Where * = free and - = allocated.

Sorta looks like Swiss cheese, or the barn in Black Sunday.

Theoretically, the worst thing you can do is allocate a bunch of blocks
and free every second block.  Sounds a lot like FreeRemember(FALSE).

It would be better to hang on the the little blocks and use FreeRemember(TRUE)
at the end of your program.

It would be _even_ better if Intuition used a memory-pool manager from
which to draw the Remember-headers.  It would be _even_even_ better
if Intuition itself stopped using FreeRemember(FALSE) itself, but
that's another topic.

     Peter
--
Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc.
{uunet|rutgers}!cbmvax!peter    peter@cbmvax.commodore.com
My opinions do not necessarily represent the opinions of my employer.
"If all you have is a hammer, everything looks like a nail."

eeh@public.BTR.COM (Eduardo E. Horvath eeh@btr.com) (05/26/91)

I read the RKM Intuition manual at least five times trying to puzzle out
the use for AllocRemember() and FreeRemeber().  I always thought I was
missing something.  Why would anyone want to allocate a large number
of memory blocks, and then forget what they allocated?  What is the
reason for FreeRemeber(FALSE) ?



-- 
=========================================================================
Eduardo Horvath				eeh@btr.com
					..!{decwrl,mips,fernwood}!btr!eeh
	"Trust me, I am cognizant of what I am doing." - Hammeroid

ahh@glyph.kingston.ny.us (Andy Heffernan) (05/26/91)

In article <21838@cbmvax.commodore.com> peter@cbmvax.commodore.com (Peter Cherna) writes:
>In article <1991May23.114423.11039@medar.com> jseymour@medar.com (James Seymour) writes:
>>But if you eventually F/free() the other two, the three chunks of memory
>>(in the above example) will be coalesced by the o/s, won't they?
>
>I'm not a fragging expert, but I've always assumed the system was
>happier if you tried to free things in reverse order.  (Intervening
>processes may make allocations.)  It's also a generally good programming
>practice.

Well, sorta.

For your typical coalescing memory allocator, given that the heap starts out 
unfragmented at time t1, and -all- allocations/frees are perfectly nested 
until time t2, there will be no fragmentation in the heap at any point 
between t1 and t2.  It's not really a heap anymore, it's a stack.
Given that nearly all allocations on the Amiga come from the common
system heap (AllocMem/FreeMem), however, maintaining perfect nesting 
of allocations is clearly impossible.  Performing allocations from a
per-process memory pool (a la sbrk()/malloc()) allows a process total 
control over its heap and helps to localize any eliminate fragmentation.

At any rate, if between t1 and t2 (same initial conditions as above), 
n random tasks madly allocate and free memory from the system heap
in any order, but all memory is guaranteed to have been freed by t2, 
there should be no fragmentation at time t2.  If there is, either the 
coalescer has a bug or not everything has actually been freed.

-- 
-------------------------------------------------------------------------
  Andy Heffernan		文字		uunet!glyph!ahh

ken@cbmvax.commodore.com (Ken Farinsky - CATS) (05/28/91)

In article <2885@public.BTR.COM> eeh@public.BTR.COM (Eduardo E. Horvath  eeh@btr.com) writes:
>I read the RKM Intuition manual at least five times trying to puzzle out
>the use for AllocRemember() and FreeRemeber().  I always thought I was
>missing something.  Why would anyone want to allocate a large number
>of memory blocks, and then forget what they allocated?  What is the
>reason for FreeRemeber(FALSE) ?

AllocRemember() returns a pointer to the memory block as well as linking
the allocation into the remember chain.  If you save the pointer to
the memory block and call FreeRemember(FALSE), you can then track the
memory yourself and later free it with a call to FreeMem().  It is much
more efficient to just use AllocMem()/FreeMem() and forget AllocRemember().
-- 
--
Ken Farinsky - CATS - (215) 431-9421 - Commodore Business Machines
uucp: ken@cbmvax.commodore.com   or  ...{uunet,rutgers}!cbmvax!ken
bix:  kfarinsky

peter@cbmvax.commodore.com (Peter Cherna) (05/28/91)

In article <2885@public.BTR.COM> eeh@public.BTR.COM (Eduardo E. Horvath  eeh@btr.com) writes:
>What is the reason for FreeRemeber(FALSE) ?

There isn't a very good reason for it. The best reason I can give is based
on the way OpenWindow() and OpenScreen() use AllocRemember.

Using AllocRemember() allows for easy freeing in case of an allocation
failure.  Then, when the window or screen or whatever succeeds,
FreeRemember(FALSE) is called, which increases the amount of memory
available.  Of course, it makes freeing the window or screen at 
CloseWindow()/CloseScreen() time more complex, and it frags memory.

So there's not really much use, but remember, the first Amigas shipped
with 256K of RAM on board, and they were originally going to have
128K on board, so all those little headers did add up to something.

>Eduardo Horvath				eeh@btr.com

     Peter
--
Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc.
{uunet|rutgers}!cbmvax!peter    peter@cbmvax.commodore.com
My opinions do not necessarily represent the opinions of my employer.
"If all you have is a hammer, everything looks like a nail."

markv@kuhub.cc.ukans.edu (05/29/91)

In article <2885@public.BTR.COM>, eeh@public.BTR.COM (Eduardo E. Horvath  eeh@btr.com) writes:
> I read the RKM Intuition manual at least five times trying to puzzle out
> the use for AllocRemember() and FreeRemeber().  I always thought I was
> missing something.  Why would anyone want to allocate a large number
> of memory blocks, and then forget what they allocated?  What is the
> reason for FreeRemeber(FALSE) ?

Well, Alloc/Free remember can be useful for backing out of a long
chain of allocations part-way through if you have an error.  For
instance I had window I built with 30 bazzillion gads and menu items.
During the build I used AllocRemember() and did a FreeRemember() if I
had a problem.  If I suceeded then I called FreeRemeber(FALSE) because
all the allocated memory was hanging off my window as the menu strip,
gads, etc.  So at death time I looped though killing each item.

Yeah, sounds dumb and was, but that was the idea between
FreeRemember(FALSE).  I ended up just FreeRemember(TRUE) after I
killed the window.  I also wrote my own Alloc/Free to track allocations, and
report mismatches in address and size, dangling allocations at program
exit, etc.  To avoid fragging I put the Remember struct in front of
the allocation and allocated one block instead of two.  I also have
manage my own malloc like private pools use (this
greatly helps fragmentation).  Really big things (>1K) I allocate
directly from the system, these aren't common.  Medium things (100-1K)
I allocate from a variable size pool, small things (<100 bytes) get
rounded up to 100 bytes and come out of a seperate pool.  This
seperate pool for really small things tremendously cuts fragging since
it is these things that come and go so fast and can fragment terrbily
(messages, etc).

I'm playing with some Alloc/Free replacements for exec.library that do
similar things as well as "best-fit" allocation instead of "first-fit".

The problem here is it really helps to have a task private tracking pool but
doing this on exec.library is tough (almost nobody OpenLibrary()s
exec.library).

One bit of expirimentation determined that rounding up all allocations
to the nearest power of 2 (ie 1K 2K 4K) with a limit on max
granualarity (32K works well since it will hold the average bitplane
which is one of the largest common come/go allocations) in conjunction
with best-fit allocations seems to almost completely eliminate fragging.
-- 
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
Mark Gooderum			Only...		¥    Good Cheer !!!
Academic Computing Services	       ///	  ¥___________________________
University of Kansas		     ///  /|         __    _
Bix:	  mgooderum	      ¥¥¥  ///  /__| |¥/| | | _   /_¥  makes it
Bitnet:   MARKV@UKANVAX		¥/¥/  /    | |  | | |__| /   ¥ possible...
Internet: markv@kuhub.cc.ukans.edu
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

ben@epmooch.UUCP (Rev. Ben A. Mesander) (05/29/91)

In article <1991May28.162254.31102@kuhub.cc.ukans.edu> markv@kuhub.cc.ukans.edu writes:

[...]

>I'm playing with some Alloc/Free replacements for exec.library that do
>similar things as well as "best-fit" allocation instead of "first-fit".

It would be nice to have a memory allocation debugging tool for those
of us who are not lucky enough to have an MMU. One thing though; I thought
common wisdom was that best fit allocation often produces more fragmentation
than first fit allocation. Am I out of date?

>The problem here is it really helps to have a task private tracking pool but
>doing this on exec.library is tough (almost nobody OpenLibrary()s
>exec.library).

Well, maybe your program would provide an incentive :-)

>One bit of expirimentation determined that rounding up all allocations
>to the nearest power of 2 (ie 1K 2K 4K) with a limit on max
>granualarity (32K works well since it will hold the average bitplane
>which is one of the largest common come/go allocations) in conjunction
>with best-fit allocations seems to almost completely eliminate fragging.

What do you do with very small allocations?

--
| ben@epmooch.UUCP   (Ben Mesander)       | "Cash is more important than |
| ben%servalan.UUCP@uokmax.ecn.uoknor.edu |  your mother." - Al Shugart, |
| !chinet!uokmax!servalan!epmooch!ben     |  CEO, Seagate Technologies   |