LWN.net Logo

When in doubt, add another layer of indirection

When in doubt, add another layer of indirection

Posted Jun 1, 2011 21:25 UTC (Wed) by sethml (subscriber, #8471)
Parent article: Object-oriented design patterns in the kernel, part 1

Curious question from a non-kernel-hacker: it seems like the kernel could save a lot of memory (particularly on 64-bit systems) by replacing vtable pointers by smaller array indices. For example, every inode in the system contains an inode_operations pointer, occupying 64 bits:

struct inode {
        /* RCU path lookup touches following: */
        umode_t                 i_mode;
        uid_t                   i_uid;
        gid_t                   i_gid;
        const struct inode_operations   *i_op;
        struct super_block      *i_sb;
        ...
}

... foo->i_op->bar(...);
It'd be possible to save 52 bits per inode, which could add up if you have a lot of inodes in memory:
struct inode {
        ...
        uint16_t i_op_idx;
        ...
}

struct inode_operations inode_ops[MAX_INODE_OPS];

... inode_ops[foo->i_op_idx].bar(...);
The same technique could be used for a lot of structure members which aren't vtable pointers - for example, i_sb seems like a potential candidate. Disadvantages: need to set an upper limit on the number of inode_operations structures, a bit slower (extra indirection), complicates the code. Given appropriate infrastructure, the code complication could be centralized in some helper functions/macros. Thoughts? Could this be worthwhile? Are the potential memory gains too minimal to care about?


(Log in to post comments)

When in doubt, add another layer of indirection

Posted Jun 1, 2011 23:37 UTC (Wed) by darthscsi (subscriber, #8111) [Link]

Doing this without language level support for appending arrays gets really ugly. That said, the kernel plays linker script magic other places to create appending arrays.

When in doubt, add another layer of indirection

Posted Jun 2, 2011 8:33 UTC (Thu) by koverstreet (subscriber, #4296) [Link]

In order to make it work with modules you'd need to generate the idx at runtime, which would actually solve both problems...

When in doubt, add another layer of indirection

Posted Jun 3, 2011 7:57 UTC (Fri) by josh (subscriber, #17465) [Link]

Most of the time, only one copy of those structures exists, so saving a few bits doesn't seem worth the extra complexity and the extra indirection.

When in doubt, add another layer of indirection

Posted Jun 9, 2011 7:44 UTC (Thu) by kevinm (guest, #69913) [Link]

The savings are per inode, not per inode_ops.

When in doubt, add another layer of indirection

Posted Jun 3, 2011 9:04 UTC (Fri) by jengelh (subscriber, #33263) [Link]

But the 52 saved bits might be spent again in extra instructions to calculate the pointer from the extra offset that you then would have.

When in doubt, add another layer of indirection

Posted Jun 3, 2011 12:15 UTC (Fri) by dlang (✭ supporter ✭, #313) [Link]

but if you have thousands or millions of these in memory the space savings may add up

also, since the cpu runs so much faster than memory does, you can actually do quite a lot of processing in the time saved by avoiding a memory fetch.

When in doubt, add another layer of indirection

Posted Jun 9, 2011 7:43 UTC (Thu) by kevinm (guest, #69913) [Link]

This seems like a reasonable idea, although the hit to readability and simplicity is such that you'd only want to do it in places where it would make a real memory difference.

Why not try it and see?

(By the way, it'd be 48 bits that you'd save replacing a 64 bit pointer with a 16 bit index).

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds