Re: [Vala] GObject allocation / referencing... Why is so slow?



On Sat, Jan 15, 2011 at 22:53:25 +0100, Jiří Zárevúcky wrote:
2011/1/15 Aleksander Wabik <alex wabik gmail com>:
There are other relevant reasons to choose Vala over
C#, but speed is not one of them. :)
This is... very sad. JIT is cool, because it helps to get rid of
performance problems introduced by some features of OOP, but if we are
compiling to C, should we not try to solve these problems on another
level?

Maybe, if it is worth the effort.

This is not about JIT. JIT can never beat optimizing compilation in advance,
because it's just doing the same optimizations, lazily only for the pieces of
code where it helps the most.

The main difference is the allocator. A good compacting garbage collector has
extremely fast allocation and deallocation at expense of higher memory
requirement, the collection step and especially need for appropriately
instrumeted mutator. The fast allocation and deallocation makes such
collectors faster in case of many short-lived objects, but their use is
limited to properly cooperating virtual machines like Java VM or CLR.

Although Mono actually only got compacting garbage collector in 2.8, so the
test was likely with version using Boehm GC, that collector uses something
like slab allocator, making it decently fast too.

[...]

Other thing: why delete objects when refcounting drops to 0? Let's
maintain a queue of some size (maybe tweakable by a class attribute) of
objects that will be just re-initialized when operator new is called?
This is a matter of general design.


This is more interesting,

This cannot be done in such simplistic way. You need a proper memory pool
with reclamation of long unused instances and such. That is, use a slab
allocator. The GLib's slice allocator (g_slice_* functions) is one and
I thought vala already used that. Using explicit slab caches might help
though.

but then we could simply make it possible to use a garbage collector in
Vala programs to achieve yet better results.

That would be nice.

On the other hand it is quite complicated. The code itself would get rid of
all the bookkeeping and things like strings would be trivially shareable. But
the bookkeeping would have to be done when passing pointers to
collector-unaware modules and storing them in non-collector-allocated memory,
meaning it would need to know which modules were compiled with collector and
which ones without.

Also to allow use of at least heap-correct allocator to allow some
compaction, we'd need to generate some functions or metadata for the
collector to handle the marking and pointer adjustment.

If there was a good, universalish garbage collector library, that the various
runtimes (D (phobos), Go, Mono, open-jvm, python, parrot etc.) used, than
this would be easier. But most of them use their own (even when they use
Boehm GC, which exists as libgc), making any attempt on combining them in one
program mostly futile. It's vala's advantage that it can be combined with any
of them. It would loose that advantage by using a garbage collector.

[...]

Other thing: why access private data through a pointer? Oh, I read
rationale for this architecture somewhere in glib manual, but on the
other hand, we can not enforce 'protected' on C level. Maybe private
can be spared too? General design, although impact on performance
should not be high.


Dova profile prohibits non-private fields entirely. Let's do the same
in GLib profile (except bindings) and problem solved, we don't have to
care about the distinction. On the other hand, the way Dova profile
accesses object data is even less direct than GObject way. I'd like to
see what the actual performance difference is.

The reason is ABI compatibility for libraries. It is advantageous for
libraries that you can add private members without changing size of the
object, because if object size changes, code inheriting from the object will
need to be recompiled to use the new library. And since you never know what
code derives it, you'll have to bump the ABI version and all code will need
to be recompiled. So I think Dova profile should support it, but it might be
on request, since only libraries want it.

Other thing: signals. Did someone measured their performance? I did
once, its AWFUL! Why? Well, here we also are using highly reusable, and
very slow code. Signals are referenced by name (yes, string!), signals
get complicated marshallers for their parameters... I don't know if it
can be fixed easily in glib profile, but in such language like vala the
signal could be implemented as a list of function pointers! I bet that
any JIT, in C# or in Java (when java will finally support
events/signals) will beat glib signals easily. A matter of general
design.

Changing this in GObject is imo not possible.

No, but:
 1. It can be done in a simpler fashion in Dova and
 2. Even in GLib profile, any non-GObject objects could do it simpler.

Basically I always thought the GLib code is totally silly overkill. If
I remember correctly, it always converts the arguments to array of GValues
and back instead of just passing the va_args or just having appropriate
emit_signal_type1_type2_... directly (C++ makes this easier; oh well).
Languages that need to convert the arguments can do the processing on va_args
equally well as on GValues.

-- 
                                                 Jan 'Bulb' Hudec <bulb ucw cz>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]