Also the notion of collapsing permissions to a single row per object with columns (or bits) set to represent privileges isn't an obvious big win by itself.
One key element that slows down the permissions system is the fact that we don't have one row for each (object_id, grantee_id, privilege) that applies to each object_id, grantee_id pair.
Rather we just have rows for privileges that are set explicitly.
In other words, if we set "admin" we don't expand the table with entries for "read", "write" etc. We join against a hierarchy table.
This is necessary, unfortunately, for the current semantics. In the one-row-per-object model we just can't set the "write" column (or bit) for an object when we set the "admin" privilege. Or more specifically we can't blindly delete the "write" privilege when we delete the "admin" privilege - the grantee may have "write" explicitly as well as implicitly from having been granted "admin".
When I considered my bitstring implementation (one bit per perm, as mentioned above identical in concept to Branimir's notion) I couldn't see any straightforward way to maintain the current semantics. You end up wanting to store one row for each explicit grant on an object which sets not only the granted priv but all the child privs. There goes part of the supposed win ...
Maybe Branimir has figured out a simple way to track this while only storing one row per object, if so, he should share. If not, then we really don't have an alternative implementation that's a lot faster in hand, do we? Instead we have a potentially faster implementation of a permissions system with different semantics.
On the other hand the current datamodel can also be further denormalized to expand the hierarchy properly and to maintain the current semantics.
However, with a large number of permissions and complex hierarchy the tables would grow HUGE.
So I chickened out when I last visited the problem. Huge tables are more a space problem, though, not necessarily a significant performance problem given the log2(N) performance characteristics of queries on simple tables with proper indexes.
We need to get rid of custom privileges as much as possible. This will speed permissions checking without any change to the underlying datamodel at all, and will also make it more reasonable to consider various other denormalizations or changes to the underlying datamodel. "foo-read" descended from "read" which implements standard "read" semantics is a waste conceptually and in practice.