[dmd-beta] ModuleInfo compaction

Brad Roberts braddr at puremagic.com
Sun Jan 31 00:59:35 PST 2010


I like the idea of saving memory, I don't care for the implementation; all those
if's which won't be branch predictable, I expect, and adds seem like they'll
make looking up each element quite a bit more expensive.  Not to mention the
amount of code repetition.  The repetition is easy to fix, but I don't have a
good solution yet for the cost.

The easy solution (quickly written and untested, and actually increases the
runtime cost since it makes all the property functions cost as much as the worst
case):

void* calcPosition(uint mask)
{
    // NOTE: why does this use size_t explicitly rather than auto?
    size_t off = New.sizeof;
    auto flags = n.flags & mask;

    if (flags & MItlsctor)      off += o.tlsctor.sizeof;
    if (flags & MItlsdtor)      off += o.tlsdtor.sizeof;
    if (flags & MIxgetMembers)  off += o.xgetMembers.sizeof;
    if (flags & MIctor)         off += o.ctor.sizeof;
    if (flags & MIdtor)         off += o.ctor.sizeof;
    if (flags & MIictor)        off += o.ictor.sizeof;
    if (flags & MIunitTest)     off += o.unitTest.sizeof;

    if (flags & MIimportedModules)
    {
        auto plength = cast(size_t*)(cast(void*)(&this) + off);
        off += size_t.sizeof + *plength * plength.sizeof;
    }

    if (flags & MIlocalClasses)
    {
        auto plength = cast(size_t*)(cast(void*)(&this) + off);
        off += size_t.sizeof + *plength * plength.sizeof;
    }

    return cast(void*)(&this) + off;
}

Which you can call with:

@property string name()
{
    if (isNew)
    {
        auto p - cast(immutable(char)*)(calcPosition(MASKname))
        auto len = strlen(p);
        return p[0 .. len];
    }
    else
        return o.name
}

Obviously, you'll need to add the MAKS* enum to parallel the MI* enums.

One way to solve the efficiency issue, at the cost of some memory would be to
build a table of offsets.  Given the 7 fixed size elements, that's just 128
combinations of fields.  Since the size of the largest offset is less than a
byte, we can just use 7 bytes to hold the offset of each field.  That's not a
large table.  Given that table, you could pick up the offset by something like:

size_t off = table[((n.flags >> 3) & MImask)*7 + MIfieldnumtolookup]]

I haven't thought it through well enough, but rearranging the 2 lengths for the
last two fields to be before the variable length data might help a little since
they could be included in the above table.

Anyway, food for thought.

Later,
Brad


More information about the dmd-beta mailing list