Skip to content

<system_error>: Consider improving memory allocation of system_category().message() #434

@sylveon

Description

@sylveon

Currently, this method allocates 96kb of memory for each invocation by first allocating a 32k character string in the headers and then a 32k array of wchar_t in implementation files, then copying from the array to the string, and then shrink_to_fit does more allocation and copying.

STL/stl/inc/system_error

Lines 486 to 489 in 580e61a

const unsigned long _Size = 32767;
string _Narrow(_Size, '\0');
const unsigned long _Val = _Winerror_message(static_cast<unsigned long>(_Errcode), &_Narrow[0], _Size);

STL/stl/src/syserror.cpp

Lines 113 to 119 in 31bed7a

unsigned long _Message_id, char* _Narrow, unsigned long _Size) { // convert to name of Windows error, return 0 for
// failure, otherwise return number of chars
// written pre: _Size < INT_MAX
const unique_ptr<wchar_t[]> _Wide(new wchar_t[_Size]); // not using make_unique because we want default-init
const auto _First = _Wide.get();
unsigned long _Wide_chars =
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, _Message_id, 0, _First, _Size, 0);

It seems like this behavior could be improved in vNext, by making use of FORMAT_MESSAGE_ALLOCATE_BUFFER to get exactly the right size required for the message. A hypothetical _Get_Winerror_message function could return a pair<wchar_t*, std::size_t>, the headers would then allocate a std::string with the right size, calling _Copy_Winerror_message to copy (and narrow) into the std::string's buffer, and then call _Free_Winerror_message to free the buffer allocated by FormatMessage.

Sidenote: is there a reason for not using FormatMessageA? This would remove WideCharToMultiByte's overhead

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixedSomething works now, yay!performanceMust go faster

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions