-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
When retrieving the classic locale the current code calls _Init which takes a lock regardless of initialization state.
Expanded here, the code looks like the following.
_MRTIMP2_PURE const locale& __CLRCALL_PURE_OR_CDECL locale::classic() { // get reference to "C" locale
//_Init();
{
locale::_Locimp* ptr = nullptr;
_BEGIN_LOCK(_LOCK_LOCALE) // prevent double initialization
// this function just returns a global variable
// ptr = _Getgloballocale();
ptr = global_locale;
if (ptr == nullptr) { // create new locales
_Setgloballocale(ptr = _Locimp::_New_Locimp());
ptr->_Catmask = all; // set current locale to "C"
ptr->_Name = "C";
_Locimp::_Clocptr = ptr; // set classic to match
_Locimp::_Clocptr->_Incref();
::new (&classic_locale) locale(_Locimp::_Clocptr);
}
// this is always false in the classic() codepath
//if (_Do_incref) {
// ptr->_Incref();
//}
_END_LOCK()
//return ptr;
}
return classic_locale;
}This means that every call to classic() is locking and unlocking a mutex, despite that after its initialization the pointer must always be valid. This can cause huge performance issues in specific scenarios, for example https://twitter.com/aras_p/status/1558063800145813505 shows a measured ~500x performance penalty in some blender loading code due to contention on this lock.
A fast path that avoids locking (by checking whether global_locale is valid, and directly returning before entering the critical section) should drastically improve performance in this and other similar situations.
https://github.com/microsoft/STL/blob/5e7cac7f679/stl/src/locale0.cpp#L138-L141