Re: About speed



Sorry guys, I read this branch...and I disappointed.
You positioned yourself as experienced developers (at least Joanna Carter, I
think is experienced).

But you still fight for thing which seems like absolutely clean even for
novice in Win32 development.

So it born a question from me.

What is .NET preference if so experienced developers cannot know how to (and
when) allocated objects must be disposed?

Seems like if I'm not GC guru and I have not a deep understanding on .NET
architecture (which types are boxed and which are not, when they disposed by
GC, will resources free etc etc..I do not guru so I think I even not know
for all possible question I can to ask) I cannot write application with
..NET. In most cases it will worst against Win32 until I become a guru.

So same question again - what is a point to use .NET?

Seems like it will require more knowledge than usual Win32 and development
will slower. Otherwise, applications will much slower. Otherwise
applications will earn too much resources and memory.....


Alex

PS Really I do not want to be a troll. But I really want to understand what
is reasons for people to move to .NET. At least it is important for my
business future.

"Barry Kelly" <barry.j.kelly@xxxxxxxxx> wrote in message
news:98gt921hetoq5t6f92lccde7j3k0bmrt0o@xxxxxxxxxx
Robert Giesecke <Spam@xxxxxxxxx> wrote:

Most IDisposables have a finalizer, that will call Dispose when the
object is marked on a GC sweep.

This isn't right. It is *extremely* rare that a class implementing
IDisposable needs a finalizer, and most code that I see that implements
a finalizer is actually incorrectly implemented. (Even some classes in
the .NET libraries implement it incorrectly, especially in WinForms.)

The finalizer pattern looks like this:

---8<---
class T : IDisposable
{
~T() { Dispose(false); }

void IDisposable.Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
// dispose *managed* resources
// dispose *unmanaged* resources
}
}
--->8---

From this, you can see that using the finalizer pattern on a class which
isn't wrapping an unmanaged resource does *nothing* - it wastes time on
the GC finalizer thread, and wastes resources keeping track of the
finalizable object.

Every object in the .NET BCL which wraps an OS primitive already
implements a finalizer, or points to another managed object which does:
Semaphore, ManualResetEvent, FileStream, etc. (they usually use
SafeHandle descendants in .NET 2.0, which use critical finalizer
support, so that Thread.Abort won't leak resources).

Contained objects of these types (i.e. managed resources like FileStream
etc.) should be disposed of in the "if (disposing)" branch above, but
they don't need to be disposed of in the "dispose *unmanaged* resources"
section above, because they themselves are managed resources - their own
finalizers will take care of finalization.

Typically, if you're using P/Invoke and have a field of your class of
type IntPtr to hold some kind of handle, then you need to consider using
the finalizer pattern. If you're not, then you don't.

But those IDisposables will most likely
call GC.SupressFinalizer inside their Dispose method. Thus using "using"
will prevent finalizers from being executed. Finalizers can slow things
extremely down, because they to be synchronized as the GC runs in its
own thread.

You're right about finalizable objects being significantly more
expensive to collect. Check out the program I appended to this post. It
has definitions for two classes, one of which inherits from the other.
The base class implements the IDisposable pattern and the second one
implements the Finalizer pattern. Chains of both objects are built and
then (1) disposed explicitly (using IDispose), and (2) discarded.

These are the results (raw data) I get on my system:

Disposable (Dispose) 0.147
Disposable (Dispose) 0.152
Disposable (Dispose) 0.152 Average 0.156
Disposable (Dispose) 0.177 StdDev 0.011937336
Disposable (Dispose) 0.152 Range 0.03

Finalizer (Dispose) 1.034
Finalizer (Dispose) 1.031
Finalizer (Dispose) 1.032 Average 1.0354
Finalizer (Dispose) 1.04 StdDev 0.004335897
Finalizer (Dispose) 1.04 Range 0.009

Disposable (discarded) 0.055
Disposable (discarded) 0.054
Disposable (discarded) 0.054 Average 0.0544
Disposable (discarded) 0.054 StdDev 0.000547723
Disposable (discarded) 0.055 Range 0.001

Finalizer (discarded) 2.683
Finalizer (discarded) 2.672
Finalizer (discarded) 2.681 Average 2.6792
Finalizer (discarded) 2.692 StdDev 0.009471008
Finalizer (discarded) 2.668 Range 0.024

The reason a discarded object with a finalizer is so much more expensive
than one which had Dispose() called on it is that GC.SuppressFinalize()
takes it off the finalization queue. It's still not cheap, though.

(Sidenote: I know my terminology isn't totally standard with
IDisposable/Dispose pattern versus Finalizer pattern, but the .NET
documentation conflates the two issues, when they are actually distinct
yet related. All objects with a Finalizer should implement IDisposable;
but very few objects implementing IDisposable should implement a
Finalizer. A good blog entry on this dichotomy with lots more pointers
is here:

http://dotnetjunkies.com/WebLog/rajchaniansbiztalkblog/archive/2005/04/20/69429.aspx)

> And you are right. There is no way to free objects the Delphi way as
> far as I know.

It is possible, but I won't explain how. Last time I did, I had to
explain that someone why he shoot himself in the foot. You only need it,
if your design is fundamentally flawed. But then, you'd have to redesign
anyway. ;-)

One can use the Marshal class to allocate unmanaged memory (or
alternatively P/Invoke another memory manager), but then you have to use
IntPtr and unsafe code to manipulate it - you can't instantiate a
managed class over unmanaged memory.

A not-as-nasty-but-still-flawed solution would be to call GC.Collect
twice. Thus every non-collected object will be gen 1 after the first
collect and since it wasn't touched between the 1st and the 2nd, it will
be free'd after the 2nd Collect.

Actually, explicitly calling GC.Collect() once causes a full collection
of all generations. You have to call the other overload,
GC.Collect(int), if you don't want to collect all generations.

This *could* be necessary if you won't leave enough resources for the GC
Thread to do its job. In a standard user-mode application, GC will run
in a Background thread. Thus if you do a lot of crunching, GC will sweep
only if you've eaten *lots* of memory.

This isn't true. There's only a GC thread (per CPU (= per heap)) for
Server-mode GC; Workstation GC does its collection work on the thread
that caused the GC (usually because a memory allocation exceeded the
gen0 threshold).

Even for Server, it isn't quite right. GC is triggered in one of three
conditions:

1) Allocation exceeds the Gen0 threshold;
2) System.GC.Collect is called;
3) System is in low memory situation;

So, if you're doing a lot of crunching that's doing a lot of allocation,
then the GC will still be triggered by an allocation, and isn't delayed
until the OS interrupts the thread due to quantum exhaustion - there's
no risk of "eating lots of memory" unless you're keeping all your
allocations unnecessarily rooted in the stack or heap somewhere.

(In a standard user-mode application, you're end up using the
workstation GC).

Good blog entries for the GC implementation:

http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx
http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx
http://blogs.msdn.com/maoni/archive/2006/02/28/541095.aspx
http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx

I also recommend this PDC presentation:

http://microsoft.sitestream.com/PDC05/FUN/FUN421_files/intro.htm#nopreload=1&autostart=1


Finalizable / non-finalizable test program follows:

---8<---
using System;
using System.Diagnostics;

class App
{
class WithFinalizer : JustDisposable
{
public WithFinalizer()
{
}

protected override void Dispose(bool disposing)
{
if (disposing)
GC.SuppressFinalize(this);
base.Dispose(disposing);
}

~WithFinalizer()
{
Dispose(false);
}
}

class JustDisposable : IDisposable
{
public JustDisposable()
{
}

void IDisposable.Dispose()
{
Dispose(true);
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
if (Link != null)
((IDisposable) Link).Dispose();
}

public JustDisposable Link;
}

delegate void Method();

static void Benchmark(int reps, string label, Method method)
{
method();
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i < reps; ++i)
method();
Console.WriteLine("{0}, {1:f3}, {2} reps",
label,
watch.ElapsedTicks / (double) Stopwatch.Frequency,
reps);
}

static WithFinalizer CreateWithFinalizerChain(int length)
{
WithFinalizer result = null;
for (int i = 0; i < length; ++i)
{
WithFinalizer added = new WithFinalizer();
added.Link = result;
result = added;
}
return result;
}

static JustDisposable CreateJustDisposableChain(int length)
{
JustDisposable result = null;
for (int i = 0; i < length; ++i)
{
JustDisposable added = new JustDisposable();
added.Link = result;
result = added;
}
return result;
}

static void Main()
{
const int innerReps = 50000;
const int outerReps = 5;

for (int i = 0; i < outerReps; ++i)
Benchmark(innerReps, "Disposable (Dispose)", delegate
{
((IDisposable)
CreateJustDisposableChain(100)).Dispose();
});

for (int i = 0; i < outerReps; ++i)
Benchmark(innerReps, "Finalizer (Dispose)", delegate
{
((IDisposable) CreateWithFinalizerChain(100)).Dispose();
});

for (int i = 0; i < outerReps; ++i)
Benchmark(innerReps, "Disposable (discarded)", delegate
{
CreateJustDisposableChain(100);
});

for (int i = 0; i < outerReps; ++i)
Benchmark(innerReps, "Finalizer (discarded)", delegate
{
CreateWithFinalizerChain(100);
});
}
}
--->8---

-- Barry

--
http://barrkel.blogspot.com/


.



Relevant Pages

  • Re: Question on implementing IDisposable
    ... have dealth with the unmanaged resources and before you take your ... This class does not implement a finalizer ... The overloaded Dispose which takes a bool argument should be made ... Then, the base class can implement IDispose, so ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Finalization and .NET/deterministic or orderly shutdown
    ... > production worthy application really call dispose and implement a ... references to that class to use the IDispose. ... then at the very least it's in an AppDomain shutdown. ... >> A finalizer is there for objects that you just leave hanging in the air ...
    (microsoft.public.dotnet.framework)
  • RE: newbie: implementing destructors
    ... finalizer to your class means it takes longer to garbage collect (look up on ... have some 3rd party DLL which internally allocates a chunk of memory, ... environment is not aware of this memory so at no point will it clean up this ... let's call it Dispose for now which you can call ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: " //Clean Up managed resources " f&*ck
    ... time (such as releasing internal unmanaged resources). ... Since Dispose ... methods is responsible for cleaning resources, the finalizer code ... it is about 'managed resource'. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: StatusStrip control leaks its collection items
    ... As an example, here's a quote from MSDN: "To provide explicit control, implement the Dispose provided by the IDisposable. ... They aren't saying that implementing IDisposable provides an optional approach to managing unmanaged resources. ... They are saying that if an object goes to the trouble of implementing IDisposable, then the user of that object is expected to call Disposewhen they're done with it, and that the finalizer exists in order to prevent incorrect code from creating permanent problems. ... Without a complete program there is no way to know for sure why your controls aren't getting finalized. ...
    (microsoft.public.dotnet.framework)