Re: GC performance - GC fragility
- From: "Atmapuri" <janez.makovsek@xxxxxxx>
- Date: Wed, 23 Jan 2008 11:41:14 +0100
Hi!
Amen to that :)
There is another error that people make with GC when
benchmarking:
1.) When you allocate memory with GC you always
allocate on a new address in memory. To keep the
working set small, you execute compacting procedure
now and then to keep the working set inside cache.
However, if you dont use GC, the memory allocations
within the same working loop remain the same.
What this means performance wise:
6x performance gains because the memory can always
be inside cache. In case of GC, that is not easily possible.
The compacting procedure of the GC is a patch to
fix the main weak point of the GC, namely that it
violates the memory caching system. It improves
performance by a little. (30%?) in compare to
non-compacting GC.
The compaction procedure of the GC also looses
performance much sooner than standard memory
allocation, simply because it requires many times
more memory and cache size remains the same.
2.) Almost all benchmarking tests done to show
advantage of GC performance wise violate the caching
logic for example:
a.) You run a test on a list which has integers sparsed
throughout the memory instead of stored consecutively
inside an array.
b.) The tests are done on objects which are again
references allocated sparsely through memory and
not allocated continously within memory.
c.) The tests are done on really small objects or
elements which minimize the load on the GC collection
logic. (the less you allocate, the less you have to free)
d.) No memory is allocated or freed at all and therefore
memory management is not compared.
As soon you do:
1.) Your memory objects are large
2.) Stored on consecutive memory locations
3.) Memory is allocated continuously (memory
allocation logic has to be "working")
The GC falls through very hard.
On the other hand, the GC is a very nice thing for programmers
from the point of usability and I would very much like to see
the merger of both worlds, so that we can have garbage collected memory,
but can still fallback to reference counted when
needed.
..NET GC for example also has a heap, but
does not allow memory of objects to be explicitely allocated
and freed on that heap.
The funniest thing is how the referencing counting logic
is downplayed against the GC logic:
You take a List object pointing to a large number of bytes or integers
sparsed in memory and "proove" that reference counting logic for
bytes and integers which are allocated as objects is more
expensive than GC.
But the reality of programming is different:
- Small basic objects are allocated on stack and thus there is
no cost associate with reference counting.
- As soon as you allocate an array of 5-10 elements or more,
the referencing counting overhead falls to zero in compare to GC.
One of the main reasons why .NET apps appear many times
to be slow is the "implicit" cost of the code. Namely in W32
C++ or Delphi the memory is reused on a very large scale and
cache is working wonders (6x), but not so with .NET.
The trick here is that you will not find a single profiler in the world
that will show you where is the performance being lost with GC,
because you would have to write a non-managed version of the
same app to be able to see what is going on.
Typically a performance profiler will show you for .NET that GC
cost is low, which is true, but it does not show the cost of how much
is the code running slower, because the memory addresses are not
accessed consecutively and because the cache size is too small for
the working set.
Another thing:
In GC for example is not possible allocate memory without setting it to
zero, because GC is automatically setting all memory to zero, before
it is returned to the user. This is the reason why allocating arrays
in .NET has a linearly raising cost with their size but fairly constant
one in W32.
Regards!
Atmapuri
"Eric Grange" <egrangeNO@xxxxxxxxxxxxxxx> wrote in message news:47970414$1@xxxxxxxxxxxxxxxxxxxxxxxxx
As a followup to the GC perf thread, I posted a small tweak of the benchmark in the attachments (under Pierre's post), to illustrate how wrong and how easily things can go with a GC (and how tricky benchmarking memory managers outside of real-world applications is).
Basicly the original test was allocating an object with single TStringList field, and added a single short string before "releasing" the whole (ie. it wouldn't stress the markup/compaction phase of the GC at all).
My variation adds a bunch of data fields to the TTestObject (in the form of a static array, to keep the code short), along with a reference to a subobject (another TTestObject).
Instead of allocating a single object at each benchmark step, several objects are then allocated, each (but the last) with a reference to the next object in the singly-linked chain.
The outcome?
FastMM now runs it 6 times faster (not 6%), and uses more than 4 times less memory (on a dual core).
Sean, this is an example why a GC can be considered "hideously" slow: its execution complexity isn't constant (unlike FastMM), and the more you stress it, the less efficient it becomes at managing memory.
Further modification of the test so that FastMM can be found to run as many times faster than the GC as desired is left as an exercice to the astute reader ;)
As a counter-exercice and challenge, I suggest finding a variation of the test where the GC ends up running significantly faster (at least twice faster) and using less memory (at least half).
Eric
.
- Follow-Ups:
- Re: GC performance - GC fragility
- From: Andre Kaufmann
- Re: GC performance - GC fragility
- From: Andre Kaufmann
- Re: GC performance - GC fragility
- From: Stig Johansen
- Re: GC performance - GC fragility
- From: Caleb Hattingh
- Re: GC performance - GC fragility
- References:
- GC performance - GC fragility
- From: Eric Grange
- GC performance - GC fragility
- Prev by Date: Re: The future of Bold for Delphi
- Next by Date: Re: Garbage collection - performance test
- Previous by thread: GC performance - GC fragility
- Next by thread: Re: GC performance - GC fragility
- Index(es):
Relevant Pages
|