On 11/04/2013 02:48, Marvin Humphrey wrote:
For the sake of argument, consider a brute-force alternative technique for
rationalizing memory consumption: fill the SV object slot (self->ref.host_obj)
during object allocation in `VTable_Make_Obj()`, rather than creating that SV
object lazily when it's needed. Unfortunately, that's all but certain to
degrade both speed and memory consumption in the common case. It sucks that
we need two heap memory blocks for any object which is accessed from C-space
and Perl-space.
We need even more allocations. An additional SV body for the inner
object (since it's of type SvPVMG) and another SV head for the RV
referencing the inner object. But instead of malloc, Perl uses a very
efficient arena allocator for these structures. There's practically no
memory overhead and an allocation usually just means popping a value off
a linked list.
All these internals are illustrated here:
http://cpansearch.perl.org/src/RURBAN/illguts-0.42/index.html
But I guess you could say that the current system has some
effective optimizations.
Yes, I just wrapped my head around all the details, and I think it's
very nicely done. Here are some suggestions for further optimization:
Currently, we lazily allocate a Perl object when the refcount exceeds 4
even if we don't really need it. There's a common technique to store
flags in the least significant bits of an aligned pointer that could be
employed here. Assuming that SVs are always allocated on even memory
addresses, we could use the LSB of the lucy_ref_t union to signify
whether the value is a refcount or a pointer to a host object. So we'd
have all the other bits to store refcounts, and we'd only have to
allocate a Perl object if we really need it.
If we allocate a Perl object then, I'd create the RV pointing to the
inner object right away, store it in host_obj, and use it for
refcounting. This saves a bit of memory and cycles if a Clownfish object
is converted to a Perl object multiple times. Then we could also use
sv_bless directly which is a bit slower than the code in
S_lazy_init_host_obj but more forward-compatible (PL_sv_objcount will be
deprecated in Perl 5.18, for example).
And, as Marvin suggested in his sample code, caching the stash pointer
as a member of the VTable seems like a good idea.
Nick