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

Reply via email to