[PATCH] elf: dl-minimal malloc needs to respect fundamental alignment

Florian Weimer fweimer@redhat.com
Thu Jun 23 17:54:00 GMT 2016


On 06/23/2016 07:02 PM, Joseph Myers wrote:
> On Thu, 23 Jun 2016, Florian Weimer wrote:
>
>> As far as I know, we know match or exceed the C11 max_align_t requirements.
>> What we cannot do is to bump max_align_t alignment because it affects ABI.
>
> That's not obvious to me.  It shouldn't affect the ABI of any function in
> glibc, for example; it's not the sort of type you embed in other
> structures.

I'm more worried about something using _Alignas (max_align_t), affecting 
struct layout.

> Increasing max_align_t to cover _Float128 (for 32-bit x86 as
> the sole affected case) is a question I left open in my GCC _FloatN /
> _FloatNx patch posting (not included in that patch, potentially relevant
> for a followup); that issue properly applies to _Decimal128 as well.

If we hurry up, we could bump max_align_t on i386, true.  The type and 
its implied promise is still fairly new, after all.

But a path towards increasing the fundamental alignment from time to 
time is less clear to me.

We also interpret the max_align_t requirement strictly in our malloc in 
the sense that we also apply it to small allocations.  Other mallocs 
will happily return blocks with just 8-byte alignment on x86_64, where 
_Alignof (max_align_t) is 16.  Maybe this something we could address in 
the definition of max_align_t in the C standard, but its definition is 
already very confusing.

Surprisingly the impact on i386 wouldn't even be *that* severe.  The 
minimum allocation size would still be 12 (for a total chunk size of 
16).  The size range from 13 to 20 is affected most prominently: The 
total chunk size would go from 24 bytes to 32 bytes, an increase of one 
third.  But this is also the largest such increase, the subsequent ones 
are progressively smaller:

def roundup(value, align):
     return (value + align - 1) / align * align

def chunk_size(pointer_size, align, object_size):
     minimum_chunk_size = roundup(4 * pointer_size, align)
     size = roundup(object_size + pointer_size, align)
     return max(minimum_chunk_size, size)

print "size  old  new  increase"
for size in range(0, 65):
     old_size = chunk_size(4, 8, size)
     new_size = chunk_size(4, 16, size)
     increase = (float(new_size) / old_size - 1) * 100
     print "  %2d   %2d   %2d  %8.2f" % (
         size, old_size, new_size, increase)

size  old  new  increase
    0   16   16      0.00
    1   16   16      0.00
    2   16   16      0.00
    3   16   16      0.00
    4   16   16      0.00
    5   16   16      0.00
    6   16   16      0.00
    7   16   16      0.00
    8   16   16      0.00
    9   16   16      0.00
   10   16   16      0.00
   11   16   16      0.00
   12   16   16      0.00
   13   24   32     33.33
   14   24   32     33.33
   15   24   32     33.33
   16   24   32     33.33
   17   24   32     33.33
   18   24   32     33.33
   19   24   32     33.33
   20   24   32     33.33
   21   32   32      0.00
   22   32   32      0.00
   23   32   32      0.00
   24   32   32      0.00
   25   32   32      0.00
   26   32   32      0.00
   27   32   32      0.00
   28   32   32      0.00
   29   40   48     20.00
   30   40   48     20.00
   31   40   48     20.00
   32   40   48     20.00
Â…

glibc malloc is not based on size groups for allocations, but fewer, 
more granular sizes will still help to reduce fragmentation somewhat.

Maybe we should just make the change, document the increased alignment, 
and have GCC change their definition of max_align-t?

The overhead would be more pronounced if we go from 16 bytes to 32 bytes 
alignment on 64-bit architectures.

Florian



More information about the Libc-alpha mailing list