Skip to content

Improve string allocation #92652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Improve string allocation #92652

wants to merge 9 commits into from

Conversation

MBkkt
Copy link

@MBkkt MBkkt commented May 18, 2024

  • Remove unnecessary std::max in shrink_to_fit
  • Remove unnecessary condition in __recommend
  • Fix allocation for string with small_size required less bytes (24 instead of 26, 12 instead of 11, etc)

In general I think maybe for most allocators better will be add + 1 for min_cap, because 24 size class is rare:

template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr size_type __recommend(size_type __s) noexcept {
    const size_type __boundary = sizeof(value_type) < __alignment
                                     ? __alignment / sizeof(value_type)
                                     : __endian_factor;
    size_type __guess = __align_it<__boundary>(__s + 1) - 1;
    if (__guess == __min_cap) __guess = __align_it<__boundary>(__s + 2) - 1;
    return __guess;
}

https://godbolt.org/z/fGP6e11ed

#include <cstddef>
#include <cstdint>

using size_type = size_t;

template <typename long_type>
struct __long {
    long_type x;
    long_type y;
    long_type z;
};

template <typename value_type, typename long_type>
static constexpr size_type min_cap =
    (sizeof(__long<long_type>) - 1) / sizeof(value_type) > 2
        ? (sizeof(__long<long_type>) - 1) / sizeof(value_type)
        : 2;

template <typename long_type>
static constexpr size_type alignment = sizeof(long_type);

template <size_type __a>
static constexpr size_type __align_it(size_type __s) noexcept {
    return (__s + (__a - 1)) & ~(__a - 1);
}

template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr size_type __recommend(size_type __s) noexcept {
    constexpr auto __min_cap = min_cap<value_type, long_type>;
    constexpr auto __alignment = alignment<long_type>;
    if (__s < __min_cap) {
        return static_cast<size_type>(__min_cap) - 1;
    }
    const size_type __boundary = sizeof(value_type) < __alignment
                                     ? __alignment / sizeof(value_type)
                                     : __endian_factor;
    size_type __guess = __align_it<__boundary>(__s + 1) - 1;
    //if (__guess == __min_cap) __guess += __endian_factor;
    return __guess;
}

template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr auto to_alloc(size_type s) {
    return __recommend<value_type, long_type, __endian_factor>(s) + 1;
}

int main() {
    static constexpr auto char8_64 = min_cap<char, long>;
    static_assert(char8_64 == 23);
    static constexpr auto char16_64 = min_cap<char16_t, long>;
    static_assert(char16_64 == 11);
    static constexpr auto char32_64 = min_cap<char32_t, long>;
    static_assert(char32_64 == 5);
    static constexpr auto char64_64 = min_cap<long, long>;
    static_assert(char64_64 == 2);

    static constexpr auto char8_32 = min_cap<char, int>;
    static_assert(char8_32 == 11);
    static constexpr auto char16_32 = min_cap<char16_t, int>;
    static_assert(char16_32 == 5);
    static constexpr auto char32_32 = min_cap<char32_t, int>;
    static_assert(char32_32 == 2);
    static constexpr auto char64_32 = min_cap<long, int>;
    static_assert(char64_32 == 2);


    // 64 bit system, __endian_factor = 1
    static_assert(to_alloc<char, long, 1>(0) == char8_64);
    static_assert(to_alloc<char16_t, long, 1>(0) == char16_64);
    static_assert(to_alloc<char32_t, long, 1>(0) == char32_64);
    static_assert(to_alloc<long, long, 1>(0) == char64_64);

    static_assert(to_alloc<char, long, 1>(char8_64) == char8_64 + 1);
    static_assert(to_alloc<char16_t, long, 1>(char16_64) == char16_64 + 1);
    static_assert(to_alloc<char32_t, long, 1>(char32_64) == char32_64 + 1);
    static_assert(to_alloc<long, long, 1>(char64_64) == char64_64 + 1);

    static_assert(to_alloc<char, long, 1>(char8_64 + 1) == 32);
    static_assert(to_alloc<char16_t, long, 1>(char16_64 + 1) == 16);
    static_assert(to_alloc<char32_t, long, 1>(char32_64 + 1) == 8);
    static_assert(to_alloc<long, long, 1>(char64_64 + 1) == 4);


    // 64 bit system, __endian_factor = 2
    static_assert(to_alloc<char, long, 2>(0) == char8_64);
    static_assert(to_alloc<char16_t, long, 2>(0) == char16_64);
    static_assert(to_alloc<char32_t, long, 2>(0) == char32_64);
    static_assert(to_alloc<long, long, 2>(0) == char64_64);

    static_assert(to_alloc<char, long, 2>(char8_64) == char8_64 + 1);
    static_assert(to_alloc<char16_t, long, 2>(char16_64) == char16_64 + 1);
    static_assert(to_alloc<char32_t, long, 2>(char32_64) == char32_64 + 1);
    static_assert(to_alloc<long, long, 2>(char64_64) == char64_64 + 2);

    static_assert(to_alloc<char, long, 2>(char8_64 + 1) == 32);
    static_assert(to_alloc<char16_t, long, 2>(char16_64 + 1) == 16);
    static_assert(to_alloc<char32_t, long, 2>(char32_64 + 1) == 8);
    static_assert(to_alloc<long, long, 2>(char64_64 + 1) == 4);


    // 32 bit system, __endian_factor = 1
    static_assert(to_alloc<char, int, 1>(0) == char8_32);
    static_assert(to_alloc<char16_t, int, 1>(0) == char16_32);
    static_assert(to_alloc<char32_t, int, 1>(0) == char32_32);
    static_assert(to_alloc<long, int, 1>(0) == char64_32);

    static_assert(to_alloc<char, int, 1>(char8_32) == char8_32 + 1);
    static_assert(to_alloc<char16_t, int, 1>(char16_32) == char16_32 + 1);
    static_assert(to_alloc<char32_t, int, 1>(char32_32) == char32_32 + 1);
    static_assert(to_alloc<long, int, 1>(char64_32) == char64_32 + 1);

    static_assert(to_alloc<char, int, 1>(char8_32 + 1) == 16);
    static_assert(to_alloc<char16_t, int, 1>(char16_32 + 1) == 8);
    static_assert(to_alloc<char32_t, int, 1>(char32_32 + 1) == 4);
    static_assert(to_alloc<long, int, 1>(char64_32 + 1) == 4);


    // 32 bit system, __endian_factor = 2
    static_assert(to_alloc<char, int, 2>(0) == char8_32);
    static_assert(to_alloc<char16_t, int, 2>(0) == char16_32);
    static_assert(to_alloc<char32_t, int, 2>(0) == char32_32);
    static_assert(to_alloc<long, int, 2>(0) == char64_32);

    static_assert(to_alloc<char, int, 2>(char8_32) == char8_32 + 1);
    static_assert(to_alloc<char16_t, int, 2>(char16_32) == char16_32 + 1);
    static_assert(to_alloc<char32_t, int, 2>(char32_32) == 4);
    static_assert(to_alloc<long, int, 2>(char64_32) == 4);

    static_assert(to_alloc<char, int, 2>(char8_32 + 1) == 16);
    static_assert(to_alloc<char16_t, int, 2>(char16_32 + 1) == 8);
    static_assert(to_alloc<char32_t, int, 2>(char32_32 + 1) == 4);
    static_assert(to_alloc<long, int, 2>(char64_32 + 1) == 4);
}

* Remove unnecessary std::max in shrink_to_fit
* Remove unnecessary condition in __recommend
* Fix allocation for string with small_size required less bytes (24 instead of 26, 12 instead of 11, etc)

```
#include <cstddef>
#include <cstdint>

using size_type = size_t;

template <typename long_type>
struct __long {
    long_type x;
    long_type y;
    long_type z;
};

template <typename value_type, typename long_type>
static constexpr size_type min_cap =
    (sizeof(__long<long_type>) - 1) / sizeof(value_type) > 2
        ? (sizeof(__long<long_type>) - 1) / sizeof(value_type)
        : 2;

template <typename long_type>
static constexpr size_type alignment = sizeof(long_type);

template <size_type __a>
static constexpr size_type __align_it(size_type __s) noexcept {
    return (__s + (__a - 1)) & ~(__a - 1);
}

template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr size_type __recommend(size_type __s) noexcept {
    constexpr auto __min_cap = min_cap<value_type, long_type>;
    constexpr auto __alignment = alignment<long_type>;
    if (__s < __min_cap) {
        return static_cast<size_type>(__min_cap) - 1;
    }
    const size_type __boundary = sizeof(value_type) < __alignment
                                     ? __alignment / sizeof(value_type)
                                     : __endian_factor;
    size_type __guess = __align_it<__boundary>(__s + 1) - 1;
    //if (__guess == __min_cap) __guess += __endian_factor;
    return __guess;
}

template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr auto to_alloc(size_type s) {
    return __recommend<value_type, long_type, __endian_factor>(s) + 1;
}

int main() {
    static constexpr auto char8_64 = min_cap<char, long>;
    static_assert(char8_64 == 23);
    static constexpr auto char16_64 = min_cap<char16_t, long>;
    static_assert(char16_64 == 11);
    static constexpr auto char32_64 = min_cap<char32_t, long>;
    static_assert(char32_64 == 5);
    static constexpr auto char64_64 = min_cap<long, long>;
    static_assert(char64_64 == 2);

    static constexpr auto char8_32 = min_cap<char, int>;
    static_assert(char8_32 == 11);
    static constexpr auto char16_32 = min_cap<char16_t, int>;
    static_assert(char16_32 == 5);
    static constexpr auto char32_32 = min_cap<char32_t, int>;
    static_assert(char32_32 == 2);
    static constexpr auto char64_32 = min_cap<long, int>;
    static_assert(char64_32 == 2);


    // 64 bit system, __endian_factor = 1
    static_assert(to_alloc<char, long, 1>(0) == char8_64);
    static_assert(to_alloc<char16_t, long, 1>(0) == char16_64);
    static_assert(to_alloc<char32_t, long, 1>(0) == char32_64);
    static_assert(to_alloc<long, long, 1>(0) == char64_64);

    static_assert(to_alloc<char, long, 1>(char8_64) == char8_64 + 1);
    static_assert(to_alloc<char16_t, long, 1>(char16_64) == char16_64 + 1);
    static_assert(to_alloc<char32_t, long, 1>(char32_64) == char32_64 + 1);
    static_assert(to_alloc<long, long, 1>(char64_64) == char64_64 + 1);

    static_assert(to_alloc<char, long, 1>(char8_64 + 1) == 32);
    static_assert(to_alloc<char16_t, long, 1>(char16_64 + 1) == 16);
    static_assert(to_alloc<char32_t, long, 1>(char32_64 + 1) == 8);
    static_assert(to_alloc<long, long, 1>(char64_64 + 1) == 4);


    // 64 bit system, __endian_factor = 2
    static_assert(to_alloc<char, long, 2>(0) == char8_64);
    static_assert(to_alloc<char16_t, long, 2>(0) == char16_64);
    static_assert(to_alloc<char32_t, long, 2>(0) == char32_64);
    static_assert(to_alloc<long, long, 2>(0) == char64_64);

    static_assert(to_alloc<char, long, 2>(char8_64) == char8_64 + 1);
    static_assert(to_alloc<char16_t, long, 2>(char16_64) == char16_64 + 1);
    static_assert(to_alloc<char32_t, long, 2>(char32_64) == char32_64 + 1);
    static_assert(to_alloc<long, long, 2>(char64_64) == char64_64 + 2);

    static_assert(to_alloc<char, long, 2>(char8_64 + 1) == 32);
    static_assert(to_alloc<char16_t, long, 2>(char16_64 + 1) == 16);
    static_assert(to_alloc<char32_t, long, 2>(char32_64 + 1) == 8);
    static_assert(to_alloc<long, long, 2>(char64_64 + 1) == 4);


    // 32 bit system, __endian_factor = 1
    static_assert(to_alloc<char, int, 1>(0) == char8_32);
    static_assert(to_alloc<char16_t, int, 1>(0) == char16_32);
    static_assert(to_alloc<char32_t, int, 1>(0) == char32_32);
    static_assert(to_alloc<long, int, 1>(0) == char64_32);

    static_assert(to_alloc<char, int, 1>(char8_32) == char8_32 + 1);
    static_assert(to_alloc<char16_t, int, 1>(char16_32) == char16_32 + 1);
    static_assert(to_alloc<char32_t, int, 1>(char32_32) == char32_32 + 1);
    static_assert(to_alloc<long, int, 1>(char64_32) == char64_32 + 1);

    static_assert(to_alloc<char, int, 1>(char8_32 + 1) == 16);
    static_assert(to_alloc<char16_t, int, 1>(char16_32 + 1) == 8);
    static_assert(to_alloc<char32_t, int, 1>(char32_32 + 1) == 4);
    static_assert(to_alloc<long, int, 1>(char64_32 + 1) == 4);


    // 32 bit system, __endian_factor = 2
    static_assert(to_alloc<char, int, 2>(0) == char8_32);
    static_assert(to_alloc<char16_t, int, 2>(0) == char16_32);
    static_assert(to_alloc<char32_t, int, 2>(0) == char32_32);
    static_assert(to_alloc<long, int, 2>(0) == char64_32);

    static_assert(to_alloc<char, int, 2>(char8_32) == char8_32 + 1);
    static_assert(to_alloc<char16_t, int, 2>(char16_32) == char16_32 + 1);
    static_assert(to_alloc<char32_t, int, 2>(char32_32) == 4);
    static_assert(to_alloc<long, int, 2>(char64_32) == 4);

    static_assert(to_alloc<char, int, 2>(char8_32 + 1) == 16);
    static_assert(to_alloc<char16_t, int, 2>(char16_32 + 1) == 8);
    static_assert(to_alloc<char32_t, int, 2>(char32_32 + 1) == 4);
    static_assert(to_alloc<long, int, 2>(char64_32 + 1) == 4);
}
```
@MBkkt MBkkt requested a review from a team as a code owner May 18, 2024 14:41
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label May 18, 2024
@llvmbot
Copy link
Member

llvmbot commented May 18, 2024

@llvm/pr-subscribers-libcxx

Author: Valery Mironov (MBkkt)

Changes
  • Remove unnecessary std::max in shrink_to_fit
  • Remove unnecessary condition in __recommend
  • Fix allocation for string with small_size required less bytes (24 instead of 26, 12 instead of 11, etc)

https://godbolt.org/z/fGP6e11ed

#include &lt;cstddef&gt;
#include &lt;cstdint&gt;

using size_type = size_t;

template &lt;typename long_type&gt;
struct __long {
    long_type x;
    long_type y;
    long_type z;
};

template &lt;typename value_type, typename long_type&gt;
static constexpr size_type min_cap =
    (sizeof(__long&lt;long_type&gt;) - 1) / sizeof(value_type) &gt; 2
        ? (sizeof(__long&lt;long_type&gt;) - 1) / sizeof(value_type)
        : 2;

template &lt;typename long_type&gt;
static constexpr size_type alignment = sizeof(long_type);

template &lt;size_type __a&gt;
static constexpr size_type __align_it(size_type __s) noexcept {
    return (__s + (__a - 1)) &amp; ~(__a - 1);
}

template &lt;typename value_type, typename long_type, size_type __endian_factor&gt;
static constexpr size_type __recommend(size_type __s) noexcept {
    constexpr auto __min_cap = min_cap&lt;value_type, long_type&gt;;
    constexpr auto __alignment = alignment&lt;long_type&gt;;
    if (__s &lt; __min_cap) {
        return static_cast&lt;size_type&gt;(__min_cap) - 1;
    }
    const size_type __boundary = sizeof(value_type) &lt; __alignment
                                     ? __alignment / sizeof(value_type)
                                     : __endian_factor;
    size_type __guess = __align_it&lt;__boundary&gt;(__s + 1) - 1;
    //if (__guess == __min_cap) __guess += __endian_factor;
    return __guess;
}

template &lt;typename value_type, typename long_type, size_type __endian_factor&gt;
static constexpr auto to_alloc(size_type s) {
    return __recommend&lt;value_type, long_type, __endian_factor&gt;(s) + 1;
}

int main() {
    static constexpr auto char8_64 = min_cap&lt;char, long&gt;;
    static_assert(char8_64 == 23);
    static constexpr auto char16_64 = min_cap&lt;char16_t, long&gt;;
    static_assert(char16_64 == 11);
    static constexpr auto char32_64 = min_cap&lt;char32_t, long&gt;;
    static_assert(char32_64 == 5);
    static constexpr auto char64_64 = min_cap&lt;long, long&gt;;
    static_assert(char64_64 == 2);

    static constexpr auto char8_32 = min_cap&lt;char, int&gt;;
    static_assert(char8_32 == 11);
    static constexpr auto char16_32 = min_cap&lt;char16_t, int&gt;;
    static_assert(char16_32 == 5);
    static constexpr auto char32_32 = min_cap&lt;char32_t, int&gt;;
    static_assert(char32_32 == 2);
    static constexpr auto char64_32 = min_cap&lt;long, int&gt;;
    static_assert(char64_32 == 2);


    // 64 bit system, __endian_factor = 1
    static_assert(to_alloc&lt;char, long, 1&gt;(0) == char8_64);
    static_assert(to_alloc&lt;char16_t, long, 1&gt;(0) == char16_64);
    static_assert(to_alloc&lt;char32_t, long, 1&gt;(0) == char32_64);
    static_assert(to_alloc&lt;long, long, 1&gt;(0) == char64_64);

    static_assert(to_alloc&lt;char, long, 1&gt;(char8_64) == char8_64 + 1);
    static_assert(to_alloc&lt;char16_t, long, 1&gt;(char16_64) == char16_64 + 1);
    static_assert(to_alloc&lt;char32_t, long, 1&gt;(char32_64) == char32_64 + 1);
    static_assert(to_alloc&lt;long, long, 1&gt;(char64_64) == char64_64 + 1);

    static_assert(to_alloc&lt;char, long, 1&gt;(char8_64 + 1) == 32);
    static_assert(to_alloc&lt;char16_t, long, 1&gt;(char16_64 + 1) == 16);
    static_assert(to_alloc&lt;char32_t, long, 1&gt;(char32_64 + 1) == 8);
    static_assert(to_alloc&lt;long, long, 1&gt;(char64_64 + 1) == 4);


    // 64 bit system, __endian_factor = 2
    static_assert(to_alloc&lt;char, long, 2&gt;(0) == char8_64);
    static_assert(to_alloc&lt;char16_t, long, 2&gt;(0) == char16_64);
    static_assert(to_alloc&lt;char32_t, long, 2&gt;(0) == char32_64);
    static_assert(to_alloc&lt;long, long, 2&gt;(0) == char64_64);

    static_assert(to_alloc&lt;char, long, 2&gt;(char8_64) == char8_64 + 1);
    static_assert(to_alloc&lt;char16_t, long, 2&gt;(char16_64) == char16_64 + 1);
    static_assert(to_alloc&lt;char32_t, long, 2&gt;(char32_64) == char32_64 + 1);
    static_assert(to_alloc&lt;long, long, 2&gt;(char64_64) == char64_64 + 2);

    static_assert(to_alloc&lt;char, long, 2&gt;(char8_64 + 1) == 32);
    static_assert(to_alloc&lt;char16_t, long, 2&gt;(char16_64 + 1) == 16);
    static_assert(to_alloc&lt;char32_t, long, 2&gt;(char32_64 + 1) == 8);
    static_assert(to_alloc&lt;long, long, 2&gt;(char64_64 + 1) == 4);


    // 32 bit system, __endian_factor = 1
    static_assert(to_alloc&lt;char, int, 1&gt;(0) == char8_32);
    static_assert(to_alloc&lt;char16_t, int, 1&gt;(0) == char16_32);
    static_assert(to_alloc&lt;char32_t, int, 1&gt;(0) == char32_32);
    static_assert(to_alloc&lt;long, int, 1&gt;(0) == char64_32);

    static_assert(to_alloc&lt;char, int, 1&gt;(char8_32) == char8_32 + 1);
    static_assert(to_alloc&lt;char16_t, int, 1&gt;(char16_32) == char16_32 + 1);
    static_assert(to_alloc&lt;char32_t, int, 1&gt;(char32_32) == char32_32 + 1);
    static_assert(to_alloc&lt;long, int, 1&gt;(char64_32) == char64_32 + 1);

    static_assert(to_alloc&lt;char, int, 1&gt;(char8_32 + 1) == 16);
    static_assert(to_alloc&lt;char16_t, int, 1&gt;(char16_32 + 1) == 8);
    static_assert(to_alloc&lt;char32_t, int, 1&gt;(char32_32 + 1) == 4);
    static_assert(to_alloc&lt;long, int, 1&gt;(char64_32 + 1) == 4);


    // 32 bit system, __endian_factor = 2
    static_assert(to_alloc&lt;char, int, 2&gt;(0) == char8_32);
    static_assert(to_alloc&lt;char16_t, int, 2&gt;(0) == char16_32);
    static_assert(to_alloc&lt;char32_t, int, 2&gt;(0) == char32_32);
    static_assert(to_alloc&lt;long, int, 2&gt;(0) == char64_32);

    static_assert(to_alloc&lt;char, int, 2&gt;(char8_32) == char8_32 + 1);
    static_assert(to_alloc&lt;char16_t, int, 2&gt;(char16_32) == char16_32 + 1);
    static_assert(to_alloc&lt;char32_t, int, 2&gt;(char32_32) == 4);
    static_assert(to_alloc&lt;long, int, 2&gt;(char64_32) == 4);

    static_assert(to_alloc&lt;char, int, 2&gt;(char8_32 + 1) == 16);
    static_assert(to_alloc&lt;char16_t, int, 2&gt;(char16_32 + 1) == 8);
    static_assert(to_alloc&lt;char32_t, int, 2&gt;(char32_32 + 1) == 4);
    static_assert(to_alloc&lt;long, int, 2&gt;(char64_32 + 1) == 4);
}

Full diff: https://github.com/llvm/llvm-project/pull/92652.diff

1 Files Affected:

  • (modified) libcxx/include/string (+1-7)
diff --git a/libcxx/include/string b/libcxx/include/string
index 1db803e822d72..4d66e1a6be31e 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1984,13 +1984,8 @@ private:
   }
   enum { __alignment = 8 };
   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __s) _NOEXCEPT {
-    if (__s < __min_cap) {
-      return static_cast<size_type>(__min_cap) - 1;
-    }
     const size_type __boundary = sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : __endian_factor;
     size_type __guess          = __align_it<__boundary>(__s + 1) - 1;
-    if (__guess == __min_cap)
-      __guess += __endian_factor;
     return __guess;
   }
 
@@ -3249,8 +3244,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re
   if (__requested_capacity <= capacity())
     return;
 
-  size_type __target_capacity = std::max(__requested_capacity, size());
-  __target_capacity           = __recommend(__target_capacity);
+  __target_capacity = __recommend(__target_capacity);
   if (__target_capacity == capacity())
     return;
 

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you expand a bit on why you think these are unnecessary? All of these checks look like they're required for correctness according to the standard or to keep string-internal invariants.

@MBkkt
Copy link
Author

MBkkt commented May 18, 2024

@philnik777

Could you expand a bit on why you think these are unnecessary? All of these checks look like they're required for correctness according to the standard or to keep string-internal invariants.

Change 1

    if (__s < __min_cap) {
      return static_cast<size_type>(__min_cap) - 1;
    }

This is unnecessary because __recommend always called when __s doesn't fit to sso.
It's not required by standard because part of implementation

Change 2: Already done here 4562efc

  if (__requested_capacity <= capacity())
    return;

  size_type __target_capacity = std::max(__requested_capacity, size());
  __target_capacity           = __recommend(__target_capacity);

size_type __target_capacity = std::max(__requested_capacity, size()); is unnecessary because size() <= capacity().
It's not required by standard because part of implementation.

Change 3

    if (__guess == __min_cap)
      __guess += __endian_factor;

I'm not sure about best option, but current code is definitely not the best option.

When string user requested 23/11/5 characters (char, char16_t, char32_t), we need only 24 bytes from allocator, without reason now we requesting 25/26 bytes (depends on endianness)

This change makes it request 24 bytes in such cases.

It's not required by standard because part of implementation.

@MBkkt MBkkt requested a review from philnik777 May 18, 2024 15:14
@MBkkt
Copy link
Author

MBkkt commented May 23, 2025

@philnik777 Hello, can you review this PR? If something not clear I can try to explain it with other words

Copy link

github-actions bot commented May 23, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants