Skip to content
  • Jeremy Evans's avatar
    ce51ef30
    Save one VALUE per embedded RTypedData · ce51ef30
    Jeremy Evans authored
    This halves the amount of memory used for embedded RTypedData if they
    are one VALUE (8 bytes on 64-bit platforms) over the slot size limit.
    
    For Set, on 64-bit it uses an embedded 56-byte struct.  With the
    previous implementation, the embedded structs starts at offset 32,
    resulting in a total size of 88.  Since that is over the 80 byte
    limit, it goes to the next highest bucket, 160 bytes, wasting 72
    bytes.  This allows it to fit in a 80 byte bucket, which reduces
    the total size for small sets of from 224 bytes (160 bytes
    embedded, 64 bytes malloc, 72 bytes wasted in embedding) to 144
    bytes (80 bytes embedded, 64 bytes malloc, 0 bytes wasted in
    embedding).
    
    Any other embedded RTypedData will see similar advantages if they
    are currently one VALUE over the limit.
    
    To implement this, remove the typed_flag from struct RTypedData.
    Embed the typed_flag information in the type member, which is
    now a tagged pointer using VALUE type, using the bottom low 2 bits
    as flags (1 bit for typed flag, the other for the embedded flag).
    To get the actual pointer, RTYPEDDATA_TYPE masks out
    the low 2 bits and then casts.  That moves the RTypedData data
    pointer from offset 32 to offset 24 (on 64-bit).
    
    Vast amount of code in the internals (and probably external C
    extensions) expects the following code to work for both RData and
    non-embedded RTypedData:
    
    ```c
    DATA_PTR(obj) = some_pointer;
    ```
    
    Allow this to work by moving the data pointer in RData between
    the dmark and dfree pointers, so it is at the same offset (24
    on 64-bit).
    
    Other than these changes to the include files, the only changes
    needed were to gc.c, to account for the new struct layouts,
    handle setting the low bits in the type member, and to use
    RTYPEDDATA_TYPE(obj) instead of RTYPEDDATA(obj)->type.
    ce51ef30
    Save one VALUE per embedded RTypedData
    Jeremy Evans authored
    This halves the amount of memory used for embedded RTypedData if they
    are one VALUE (8 bytes on 64-bit platforms) over the slot size limit.
    
    For Set, on 64-bit it uses an embedded 56-byte struct.  With the
    previous implementation, the embedded structs starts at offset 32,
    resulting in a total size of 88.  Since that is over the 80 byte
    limit, it goes to the next highest bucket, 160 bytes, wasting 72
    bytes.  This allows it to fit in a 80 byte bucket, which reduces
    the total size for small sets of from 224 bytes (160 bytes
    embedded, 64 bytes malloc, 72 bytes wasted in embedding) to 144
    bytes (80 bytes embedded, 64 bytes malloc, 0 bytes wasted in
    embedding).
    
    Any other embedded RTypedData will see similar advantages if they
    are currently one VALUE over the limit.
    
    To implement this, remove the typed_flag from struct RTypedData.
    Embed the typed_flag information in the type member, which is
    now a tagged pointer using VALUE type, using the bottom low 2 bits
    as flags (1 bit for typed flag, the other for the embedded flag).
    To get the actual pointer, RTYPEDDATA_TYPE masks out
    the low 2 bits and then casts.  That moves the RTypedData data
    pointer from offset 32 to offset 24 (on 64-bit).
    
    Vast amount of code in the internals (and probably external C
    extensions) expects the following code to work for both RData and
    non-embedded RTypedData:
    
    ```c
    DATA_PTR(obj) = some_pointer;
    ```
    
    Allow this to work by moving the data pointer in RData between
    the dmark and dfree pointers, so it is at the same offset (24
    on 64-bit).
    
    Other than these changes to the include files, the only changes
    needed were to gc.c, to account for the new struct layouts,
    handle setting the low bits in the type member, and to use
    RTYPEDDATA_TYPE(obj) instead of RTYPEDDATA(obj)->type.
Loading