Boost C++ Libraries: Ticket #11312: smart_ptr::detail::as_allocator::allocate() adds alignment padding when it's not needed https://svn.boost.org/trac10/ticket/11312 <p> smart_ptr::detail::as_allocator::allocate() { </p> <blockquote> <p> enum { </p> <blockquote> <p> M = boost::alignment_of&lt;type&gt;::value </p> </blockquote> <p> }; std::size_t n1 = count * sizeof(value_type); std::size_t n2 = data.size * sizeof(type); std::size_t n3 = n2 + M; CA ca(allocator()); void* p1 = ca.allocate(n1 + n3); </p> </blockquote> <p> Allocation is for two items of size n1 and n2. Alignment size is added to n2 to create n3 to there is room to align n2 properly. </p> <p> if n1 % M == 0 then alignment is already fine and the extra M bytes is wasted. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/11312 Trac 1.4.3 Peter Dimov Fri, 15 May 2015 23:28:17 GMT <link>https://svn.boost.org/trac10/ticket/11312#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:1</guid> <description> <p> I don't see why. We can only depend on the alignment of <code>p1</code> as being suitable for an object of type <code>value_type</code>. <code>n1 % M == 0</code> doesn't seem to give us anything. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Peter Dimov</dc:creator> <pubDate>Fri, 15 May 2015 23:29:40 GMT</pubDate> <title>owner changed https://svn.boost.org/trac10/ticket/11312#comment:2 https://svn.boost.org/trac10/ticket/11312#comment:2 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Peter Dimov</span> to <span class="trac-author">Glen Fernandes</span> </li> </ul> Ticket David Aue <david@…> Sat, 16 May 2015 00:31:47 GMT <link>https://svn.boost.org/trac10/ticket/11312#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:3</guid> <description> <pre class="wiki">pointer allocate(size_type count, const_void_pointer = 0) { enum { M = boost::alignment_of&lt;type&gt;::value }; std::size_t n1 = count * sizeof(value_type); std::size_t n2 = data.size * sizeof(type); std::size_t n3 = n2 + M; CA ca(allocator()); void* p1 = ca.allocate(n1 + n3); void* p2 = static_cast&lt;char*&gt;(p1) + n1; (void)boost::alignment::align(M, n2, p2, n3); *data.result = static_cast&lt;type*&gt;(p2); return static_cast&lt;value_type*&gt;(p1); } I call: boost::allocate_shared&lt;int[]&gt;(allocator, 4); Inside allocate() I see this: n1 == 20 for ms_init_tag n2 == 16 for the 4 ints M == 4 n3 == 20 ca.allocate is called with n1+n3 for a total of 40 bytes. p1 == some_address p2 == some_address + n1 boost::alignment::align called to fix p2 for 4 byte alignment p2 is unchanged by align So we allocated 40 bytes and we are using the first 20 for ms_init and the next 16 for the int[4] and then there are 4 unused bytes that are not affecting our 4 byte alignment requirement. </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Glen Fernandes</dc:creator> <pubDate>Sun, 17 May 2015 05:08:16 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:4</guid> <description> <p> One optimization I could do is instead of adding <code>alignof(type)</code> bytes: </p> <ul><li>If <code>alignof(value_type) &gt;= align(type)</code> then do not add any additional padding. </li><li>Else add <code>alignof(type) - 1</code> bytes for padding. </li></ul> </description> <category>Ticket</category> </item> <item> <author>David Aue <david@…></author> <pubDate>Sun, 17 May 2015 06:07:29 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:5</guid> <description> <p> That sounds perfect. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Glen Fernandes</dc:creator> <pubDate>Sun, 17 May 2015 06:42:57 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:6</guid> <description> <p> In fact, one step further: </p> <ul><li>If alignof(value_type) &gt;= align(type) then do not add any additional padding. </li><li>Else add alignof(type) - alignof(value_type) bytes for padding. </li></ul> </description> <category>Ticket</category> </item> <item> <dc:creator>Peter Dimov</dc:creator> <pubDate>Sun, 17 May 2015 10:20:00 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:7</guid> <description> <p> <code>CA</code> is <code>allocator&lt;char&gt;</code> and there is no guarantee for <code>p1</code> to be aligned at anything, regardless of what the alignment of <code>value_type</code> is. </p> <p> Although I suppose that the code already assumes that <code>p1</code> is aligned at <code>alignof(value_type)</code> anyway. But this assumption doesn't seem quite correct. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Glen Fernandes</dc:creator> <pubDate>Sun, 17 May 2015 16:30:07 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:8</guid> <description> <p> Good point. The above math was under the assumption that for any <code>value_type</code> the <code>allocate()</code> function for any given allocator would yield memory that is at least <code>alignof(std::max_align_t)</code> bytes aligned. </p> <p> It doesn't seem right to make this assumption, and nothing in <strong>[allocator.requirements]</strong> provides such a guarantee anyway, so I'll update the implementation accordingly. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Peter Dimov</dc:creator> <pubDate>Sun, 17 May 2015 17:15:53 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:9</guid> <description> <p> We should probably use <code>::rebind&lt;type_with_alignment&lt;alignof(value_type)&gt;::type&gt;</code> to allocate, and then the optimization would hold. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Glen Fernandes</dc:creator> <pubDate>Sun, 17 May 2015 18:10:04 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:10</guid> <description> <p> But <code>type_with_alignment&lt;alignof(value_type)&gt;::type</code> wouldn't have size <code>1</code>, right? It would have size at least <code>alignof(value_type)</code> bytes and <code>allocate()</code> takes number of objects. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Peter Dimov</dc:creator> <pubDate>Mon, 18 May 2015 10:39:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11312#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11312#comment:11</guid> <description> <p> Yes, of course. The number of objects would need to be adjusted accordingly. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Glen Fernandes</dc:creator> <pubDate>Thu, 08 Sep 2016 15:53:13 GMT</pubDate> <title>version changed https://svn.boost.org/trac10/ticket/11312#comment:12 https://svn.boost.org/trac10/ticket/11312#comment:12 <ul> <li><strong>version</strong> <span class="trac-field-old">Boost 1.57.0</span> → <span class="trac-field-new">Boost 1.63.0</span> </li> </ul> Ticket Glen Fernandes Wed, 01 Mar 2017 13:15:29 GMT status, milestone changed; resolution set https://svn.boost.org/trac10/ticket/11312#comment:13 https://svn.boost.org/trac10/ticket/11312#comment:13 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.64.0</span> </li> </ul> <p> This should be fixed in develop now after I rewrote all of allocate_shared for arrays. It will probably release with 1.65 unless the tests have enough time to cycle for 1.64 and there are no issues. </p> Ticket Glen Fernandes Fri, 03 Mar 2017 13:36:14 GMT version, milestone changed https://svn.boost.org/trac10/ticket/11312#comment:14 https://svn.boost.org/trac10/ticket/11312#comment:14 <ul> <li><strong>version</strong> <span class="trac-field-old">Boost 1.63.0</span> → <span class="trac-field-new">Boost 1.57.0</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.64.0</span> → <span class="trac-field-new">Boost 1.65.0</span> </li> </ul> <p> Will release in 1.64. </p> Ticket Glen Fernandes Sun, 26 Mar 2017 21:54:57 GMT milestone changed https://svn.boost.org/trac10/ticket/11312#comment:15 https://svn.boost.org/trac10/ticket/11312#comment:15 <ul> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.65.0</span> → <span class="trac-field-new">Boost 1.64.0</span> </li> </ul> Ticket