RE: finalization

2001-08-29 Thread Hong Zhang

 You still need to malloc() your memory; however I realize that the
 allocator can be *really* fast here.  But still, you give a lot of the
 gain back during the mark-and-sweep phase, especially if you also
 move/compact the memory.

As you said, the allocator can be really fast. Most advanced gc will
use thread local heap to allocate temp objects, so we don't even have
to sync or membar. The mark-and-sweep is ok for small heap,  1MB.

For large heap, we can use concurrent gc, multi-threaded gc, multi-heap.
Normally large heap implies SMP, so we have some cpu power to steal to
do expensive gc.

 The big gain only comes in when your program is small/quick enough to
 actually finish before the GC kicks in the first time (think CGI).  In
 that case you just discard the whole heap instead of doing a proper
 garbage collection (unless of course someone thought they 
 could still do
 something inside a finalizer during global destruction and 
 you still need
 to finalize every other object on your heap :).

As I said, the finalization should be discouraged. It is application's
problem if it uses extensive finalization, just like an application uses
bubble sort instead of qsort, there is not much we can do here. That is
one of mistakes of Java. Java promises too much. To do so, Java carries
significant overhead to fullfill its promise. For example, Java has 6+
different types of weak reference, including finalization reference.
There are very few people in the world can understand the difference.
What is the point to have them just for those smart but few people.

 Don't even dream of accessing Perl scalars simultaneously from multiple
 threads without some kind of locking.

That is the problem of Perl. In Smalltalk, every primitive object is
immutable -- Integer, Float, Fraction, Symbol. The String, Array, ByteArray
have fixed size. So there is no need for any synchronization. If you want
to mess up your Array using MT, just do it. In the end, you will get a
messy array, but you can not hurt the system/runtime in anyway.

 You want a modifiable buffer?  Get a StringBuilder
 object and lock it on every access.

That is one of stupid design of Java. If I need sync, I can do it myself.
Why StrinBuffer, Vector, Hashtable, XXXStream sync on every access? Stupid.
If I want to have a multi-read data structure, I have to write my own.
What is the point???

Hong



Re: finalization

2001-08-29 Thread Dan Sugalski

On Tue, 28 Aug 2001, Sam Tregar wrote:

 Well, there's the Perl 5 reference counting solution.  In normal cases
 DESTROY is called as soon as it can be.  Of course we're all anxious to
 get into the leaky GC boat with Java and C# because we've heard it's
 faster.  I wonder how fast it is when it's halfway under water and out of
 file descriptors.

GC has nothing to do with finalization. Many people want it to, and seem
to conflate the two, but they're separate. Dead object detection and
cleanup doesn't have to be tied to memory GC. It won't be in perl 6. The
perl 6 engine will guarantee whatever cleanup/finalization order and
timliness that Larry puts into the language definition. That's not a
problem.

FWIW, going from a manual memory management scheme to a GC scheme is
generally a good-sized performance win. Talk to the GCC people if you
don't believe that.

Dan




Re: finalization

2001-08-28 Thread Jan Dubois

On Tue, 28 Aug 2001 21:07:03 -0400 (EDT), Sam Tregar [EMAIL PROTECTED]
wrote:

On Wed, 29 Aug 2001, Jeremy Howard wrote:

 The answer used in .NET is to have a dispose() method (which is not a
 special name--just an informal standard) that the class user calls manually
 to clean up resources. It's not an ideal solution but there doesn't seem to
 be many other practical options.

Well, there's the Perl 5 reference counting solution.  In normal cases
DESTROY is called as soon as it can be.  Of course we're all anxious to
get into the leaky GC boat with Java and C# because we've heard it's
faster.  I wonder how fast it is when it's halfway under water and out of
file descriptors.

With GC, it is of course again the duty of the programmer to make sure the
resources are freed on time:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpapndx/html/_cor_finalize_and_dispose.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconcleaningupunmanagedresources.asp

C# has some syntactic sugar to make this a little more convenient to use:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfcsharpspec_8_13.asp

Having to do explicit resource management is a real pain when you are used
to Perl 5's reference counting. :)

BTW, the lure of GC over refcounting is *not* the speed (it is only
slightly faster).  The advantage is that it takes care of circular
references.  And it can remove sandbars in your heap for long running
processes.  It is also supposed to make your programs more robust because
you don't have to bother with keeping your reference counts rights.  But
it has a ton of its own problems with resource management, so I'm not
convinced there.

-Jan




Re: finalization

2001-08-28 Thread Damien Neil

On Tue, Aug 28, 2001 at 09:07:03PM -0400, Sam Tregar wrote:
 Well, there's the Perl 5 reference counting solution.  In normal cases
 DESTROY is called as soon as it can be.  Of course we're all anxious to
 get into the leaky GC boat with Java and C# because we've heard it's
 faster.  I wonder how fast it is when it's halfway under water and out of
 file descriptors.

Speaking purely for myself, I'd rather have a non-refcounting GC
because I'm rather tired of going through elaborate tricks to avoid
ever creating circular data structures.

- Damien



Re: finalization

2001-08-28 Thread Jeremy Howard

Sam Tregar wrote:
 On Wed, 29 Aug 2001, Jeremy Howard wrote:

  The answer used in .NET is to have a dispose() method (which is not a
  special name--just an informal standard) that the class user calls
manually
  to clean up resources. It's not an ideal solution but there doesn't seem
to
  be many other practical options.

 Well, there's the Perl 5 reference counting solution.  In normal cases
 DESTROY is called as soon as it can be.  Of course we're all anxious to
 get into the leaky GC boat with Java and C# because we've heard it's
 faster.  I wonder how fast it is when it's halfway under water and out of
 file descriptors.

I don't think speed is where the interest is coming from. GC should fix
common memory problems, such as the nasty circular references issue that has
caught all of us at some time.





Re: finalization

2001-08-28 Thread Jan Dubois

On Tue, 28 Aug 2001 19:04:20 -0700, Hong Zhang [EMAIL PROTECTED]
wrote:

Normally, GC is more efficient than ref count, since you will have many
advanced gc algorith to choose and don't have to pay malloc overhead.

You still need to malloc() your memory; however I realize that the
allocator can be *really* fast here.  But still, you give a lot of the
gain back during the mark-and-sweep phase, especially if you also
move/compact the memory.

The big gain only comes in when your program is small/quick enough to
actually finish before the GC kicks in the first time (think CGI).  In
that case you just discard the whole heap instead of doing a proper
garbage collection (unless of course someone thought they could still do
something inside a finalizer during global destruction and you still need
to finalize every other object on your heap :).

On MP machine, ref count is really slow, because of the atomic instructions,
which are very slow. I measured the atomic x86 instruction such as 
LOCK INC DWORD PTR [ECX]; long time ago. I believe each instruction takes
about 10 to 30 clock cycles.

Don't even dream of accessing Perl scalars simultaneously from multiple
threads without some kind of locking.  To keep their internal caching
behavior consistent, you'll need to lock them for even the most simple
operations (see the failure of the Perl 5.005 thread model).

But even if you give up the caching behavior, what about strings?  Atomic
updates, eh?  Welcome to the world of immutable strings.  Just allocate a
new string every time you need to modify it and update the string
reference atomically.  You want a modifiable buffer?  Get a StringBuilder
object and lock it on every access. :)  We could just as well switch to
Java or C#.

-Jan