[comp.sys.amiga.tech] A REAL fork

deven@rpi.edu (Deven T. Corzine) (02/23/90)

On 13 Feb 90 15:23:26 GMT, koren@hpfelg.HP.COM (Steve Koren) said:

Steve> Also, try giving it boatloads of stack.

I hate this approach.  Stack space can eat resources FAST.  Be
dynamic, dude.  Put *pointers* on your stack, and AllocMem.  Much
nicer.  Less likely to crash, too...

Steve> In other words, its not my fault! really!  :-)

Sure, sure...  :-)

Steve> And while we're discussing wish lists, can I have a fork()
Steve> command (the real thing, not the Lattice forkv() stuff) so I
Steve> can say:

Steve>       if (fork() == 0) {
Steve>          /* here's the child process */
Steve>       } else {
Steve>          /* here's the parent process */
Steve>       }

Well, I'm working on it.  It's complex, but NOT impossible.  I've got
a solution for memory swapping (if it's not obvious, don't ask.  Ugly
kludge, but absolutely necessary.) but there's still some work to do.
Besides, I'm working on fork() as a base for Amigix, and I have to do
exec() too.

Right now, high priorities are finishing the memory swapping,
implementing a filesystem (at first just a front end for AmigaDOS) and
proper fd semantics, pid's, finishing the memory swapping, and several
other things.  Then I have to write exec(), which involves (among
other things) writing a loader.  And possibly creating a new load file
format.

In any event, it won't be released soon, but anyone interested in
testing (only) with NO redistribution during development, is welcome
to send me mail and I'll consider it.  (If I don't know you, don't
count on the alpha-test list.  maybe beta.)  [Steve, I might put you
on the alpha list if you're interested.]

Deven
-- 
Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
Snail:  2151 12th St. Apt. 4, Troy, NY 12180   Phone:  (518) 274-0327
Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
Simple things should be simple and complex things should be possible.

koren@hpfelg.HP.COM (Steve Koren) (02/27/90)

> Steve> Also, try giving it boatloads of stack.

> I hate this approach.  Stack space can eat resources FAST.  Be
> dynamic, dude.  Put *pointers* on your stack, and AllocMem.  Much
> nicer.  Less likely to crash, too...

SKsh already does dynamically allocate everything of any significant
size (such as tree parse nodes, etc), and passes only a few pointers
around between functions.  However, recursion can become
quite deep, especially in the case of recursively called aliases or
shell functions.  Some functions declare quite a few automatic
variables, and it is not practical to allocate 4-byte variables
dynamically; this would kill the performance.

I do suspect that SKsh will run with less stack than I recommend.
However, there is one point which is a little unclear to me.  In AmigaDos,
when you run another program (*not* in the background) from yours,
the second program runs using the same process as the parent.  Does
this mean that it uses the same stack space, as well?  I'm not sure.
I can't find that documented anywhere, so I always recommend more stack
than should be necessary.  Feel free to try less; if it works for you,
great.

       - steve

PS - I did some emperical tests, and Lattice's malloc() is significantly
faster than AllocMem() (in addition to being standard).  It only matters
if you do alot of dynamic allocation, which SKsh does.

navas@cory.Berkeley.EDU (David C. Navas) (03/01/90)

In article <13920050@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes:
>PS - I did some emperical tests, and Lattice's malloc() is significantly
>faster than AllocMem() (in addition to being standard).  It only matters
>if you do alot of dynamic allocation, which SKsh does.

Does anyone else find this wierd?  I would suspect that malloc() is CALLING
AllocMem()...  Steve, are you telling AllocMem to clear your allocations?
[via MEMF_CLEAR]??  This would, of course, be more like calloc(), wouldn't
it?
:)

David Navas                                   navas@cory.berkeley.edu
"Think you can, think you can't -- either way it's true."  Henry Ford

riley@batcomputer.tn.cornell.edu (Daniel S. Riley) (03/01/90)

In article <22496@pasteur.Berkeley.EDU> navas@cory.Berkeley.EDU.UUCP (David C. Navas) writes:
>In article <13920050@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes:
>>PS - I did some emperical tests, and Lattice's malloc() is significantly
>>faster than AllocMem() (in addition to being standard).  It only matters
>>if you do alot of dynamic allocation, which SKsh does.

>Does anyone else find this wierd?  I would suspect that malloc() is CALLING
>AllocMem()...  

malloc() is not a straight interface to AllocMem().  It allocates memory
in minimum 4K or so chunks (you can set the minimum allocation size with 
a global variable), and manages small allocations within the chunks on its
own.  Since it doesn't go to AllocMem() on every malloc(), it isn't all
that weird that the average speed is faster.  AllocMem() has a lot of
overhead traversing the memory lists--you can do better for lots of small 
allocations by handling a chunk of memory yourself.

There is other overhead associated with using malloc, since it allocates
some extra space to keep track of the chunks it allocated and the size
of the chunks you malloc() (which it needs for free() to work).  It also
isn't entirely standard, since Lattice malloc() deals with a possibly
(usually) non-contiguous list of memory regions, but the vast majority
of applications don't care about that sort of detail (but every now and
then you find some program that depends on some bizarre detail of the
Unix memory allocator, like the free()/realloc() behavior).

This is all specific to the Lattice implimentation of malloc().  Manx does
things differently.

-Dan Riley (riley@tcgould.tn.cornell.edu, cornell!batcomputer!riley)
-Wilson Lab, Cornell University

daveh@cbmvax.commodore.com (Dave Haynie) (03/01/90)

In article <22496@pasteur.Berkeley.EDU> navas@cory.Berkeley.EDU.UUCP (David C. Navas) writes:
>In article <13920050@hpfelg.HP.COM> koren@hpfelg.HP.COM (Steve Koren) writes:
>>PS - I did some emperical tests, and Lattice's malloc() is significantly
>>faster than AllocMem() (in addition to being standard).  It only matters
>>if you do alot of dynamic allocation, which SKsh does.

>Does anyone else find this wierd?  I would suspect that malloc() is CALLING
>AllocMem()...  

While it sounds weird at first, it may not be quite that weird.  A good 
implementation of malloc() probably won't call AllocMem() for every little
allocation.  I have an allocation routine in the DiskSalv code wich works
this way.  It maintains memory lists of its own, calling AllocMem() and
making a new memory list only when there's insufficient memory already
allocated.  This could certainly waste memory over lots of individual calls
to AllocMem(), but it has a few advantages.  First of all, it eliminates
the need to track dynamic objects; you have just one FreeMem() call, which
removes the memory list, and thus, everything handed out from that list.
You also don't fragment system memory this way, even if you like to 
dynamically allocate thousands of little strings.  Secondly, AllocMem() has 
to do its work inside Forbid(), so that other tasks can't muck with 
system-wide memory lists.  So it is certainly possible that Lattice's 
malloc() runs faster, over multiple allocations, than AllocMem().

>David Navas                                   navas@cory.berkeley.edu
>"Think you can, think you can't -- either way it's true."  Henry Ford


-- 
Dave Haynie Commodore-Amiga (Systems Engineering) "The Crew That Never Rests"
   {uunet|pyramid|rutgers}!cbmvax!daveh      PLINK: hazy     BIX: hazy
                    Too much of everything is just enough

850031m@aucs.uucp (Ross MacGregor) (03/02/90)

In article <9814@batcomputer.tn.cornell.edu> riley@tcgould.tn.cornell.edu (Daniel S. Riley) writes:
[stuff on why malloc would be faster than AllocMem on average...deleted]

>This is all specific to the Lattice implimentation of malloc().  Manx does
>things differently.

So how does Manx go about doing this? 

>-Dan Riley (riley@tcgould.tn.cornell.edu, cornell!batcomputer!riley)
>-Wilson Lab, Cornell University
-- 
Ross MacGregor                                      | " Elvis Lives - I
E-mail: 850031m@AcadiaU.CA                          |   heard him on the   
UUCP:   {uunet|watmath|utai}!cs.dal.ca!aucs!850031m |   radio yesterday" 

deven@rpi.edu (Deven T. Corzine) (03/02/90)

On 27 Feb 90 15:10:38 GMT, koren@hpfelg.HP.COM (Steve Koren) said:

Steve> Also, try giving it boatloads of stack.

Deven> I hate this approach.  Stack space can eat resources FAST.  Be
Deven> dynamic, dude.  Put *pointers* on your stack, and AllocMem.
Deven> Much nicer.  Less likely to crash, too...

Steve> SKsh already does dynamically allocate everything of any
Steve> significant size (such as tree parse nodes, etc), and passes
Steve> only a few pointers around between functions.  However,
Steve> recursion can become quite deep, especially in the case of
Steve> recursively called aliases or shell functions.  Some functions
Steve> declare quite a few automatic variables, and it is not
Steve> practical to allocate 4-byte variables dynamically; this would
Steve> kill the performance.

If you're allocating a BLOCK of variables, it might work out...

Steve> I do suspect that SKsh will run with less stack than I
Steve> recommend.  However, there is one point which is a little
Steve> unclear to me.  In AmigaDos, when you run another program
Steve> (*not* in the background) from yours, the second program runs
Steve> using the same process as the parent.  Does this mean that it
Steve> uses the same stack space, as well?  I'm not sure.  I can't
Steve> find that documented anywhere, so I always recommend more stack
Steve> than should be necessary.  Feel free to try less; if it works
Steve> for you, great.

Yes.  If it will run in the same process space, it will use the same
stack.  The thing is, the memory used really builds up.  I don't know
what all SKsh is keeping in memory, but It uses a LOT of memory.  When
I exit an instance of SKsh, it usually frees about 120-150K of memory,
and that's with the 70K executable RESIDENT.  I don't consider such
excessive use of resources to be justified, so I have switched back to
using AShell.  There are several other major reasons I stopped using
SKsh -- it is EXTREMELY slow, and it also takes a LOT of memory, and
it doesn't give useful error messages -- only cryptic numbers.
Granted, I haven't tried SKsh 1.3, but it seems unlike that it
improves on the stack, memory and speed problems.

Otherwise, it's a nice shell.  Merely unusable.  (on the systems I use.)

Steve> PS - I did some emperical tests, and Lattice's malloc() is
Steve> significantly faster than AllocMem() (in addition to being
Steve> standard).  It only matters if you do alot of dynamic
Steve> allocation, which SKsh does.

How fast is "significantly" faster?

Deven
-- 
Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
Snail:  2151 12th St. Apt. 4, Troy, NY 12180   Phone:  (518) 274-0327
Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
Simple things should be simple and complex things should be possible.

phorgan@cup.portal.com (Patrick John Horgan) (03/02/90)

I suspect that malloc is faster than AllocMem because c is managing
it's own heap it AllocMem'd earlier.  Of course malloc has to manage
it's heap just the same as the Exec has to manage the Amiga's.  
A typical c sort of heap management is something that's been studied
extensively in the universities, and you can find references to tell
you optimum ways of doing it.  Another point is that the Amiga has to
worry about the (slightly) greater overhead of the memory type you are
requesting.

Patrick Horgan                       phorgan@cup.portal.com