Сохраняет ли boost::any / std::any маленькие объекты на месте?
Держать сколь угодно большие объекты, boost::any
/ std::any
безусловно, необходимо выделить пространство кучи для объектов. Тем не менее, для небольших типов, размер которых меньше или равен указателю (int,char,bool,...
), any
вместо этого можно хранить значение на месте в слоте указателя или в какой-либо другой памяти на месте и не выделять пространство кучи. Но реализация делает это?
У меня есть сценарий, где я часто храню мелкие типы в any
и только иногда более крупные типы, такие как string
s. Код довольно горячий, и поэтому я задаю вопрос. Если оптимизация не будет выполнена, мне может быть лучше иметь собственную реализацию, которая хранит мелкие типы на месте.
3 ответа
Нет никакой гарантии, но проект C++17 в [any.class] гласит, что
Реализации должны избегать использования динамически выделяемой памяти для небольшого ограниченного объекта. [Пример: где построенный объект содержит только int. - конец примера] Такая оптимизация небольших объектов должна применяться только к типам
T
для которогоis_nothrow_move_constructible_v<T>
являетсяtrue
,
К сожалению, он не дает рекомендации относительно того, что следует считать небольшим, кроме как сказать int
должны быть в состоянии храниться на месте.
Если я правильно понимаю исходный код Boost.Any, и из-за того, что тыкаю в него в отладчике, он не применяет оптимизацию небольших объектов. (Обратите внимание на безусловное использование нового.)
template<typename ValueType>
any(const ValueType & value)
: content(new holder<
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
>(value))
{
}
Ответы Натана Оливера и Джоша Келли верны: нет никакой гарантии, повышение не использует оптимизацию малых значений.
В более практических случаях https://github.com/llvm-mirror/libcxx/blob/master/include/experimental/any показывает, что libC++ (clang's) дает вам 3 пустых указателя пространства (24 байта, если они имеют ширину 8 байт)
libstdC++ только один указатель: https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/experimental/any?view=markup
изменения any
сделать размер параметра шаблона не сложно, просто вы также должны убедиться, что между any
разных размеров.
IMO, разница в производительности настолько существенная между оптимизацией небольшого размера и выделением кучи, согласно моим оценкам, и стоимостью внедрения такого маленького шаблона, который станет частью стандарта.