Поддерживает ли boost:: any/std:: какие-либо мелкие объекты на складе?
Чтобы удерживать произвольно большие объекты, boost::any
/std::any
наверняка нужно выделить кучу пространства для объектов. Однако для небольших типов, размер которых меньше или равен указателю (int,char,bool,...
), any
может вместо этого сохранить значение на месте в слоте указателя или в какой-либо другой локальной памяти и не выделять кучу пространства. Но делает ли это выполнение?
У меня есть сценарий, в котором я часто храню небольшие типы в any
и только иногда более крупные типы, такие как string
s. Код довольно жаркий, и поэтому я задаю вопрос. Если оптимизация не выполняется, мне может быть лучше с собственной реализацией, которая хранит небольшие типы на месте.
Ответы
Ответ 1
Нет гарантии, но в проекте С++ 17 указано [any.class], что
Реализации должны избегать использования динамически распределенной памяти для небольшого содержащегося объекта. [Пример: где построенный объект содержит только int. - end example] Такая оптимизация небольших объектов должна применяться только к типам T
, для которых is_nothrow_move_constructible_v<T>
- true
.
К сожалению, он не дает рекомендации относительно того, что следует считать маленьким, за исключением того, что int
должен быть сохранен на месте.
Ответ 2
Если я правильно понимаю исходный код 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))
{
}
Ответ 3
Ответы Натана Оливера и Джоша Келли верны: нет никакой гарантии, boost не использует оптимизацию небольших значений.
В более практических случаях,
https://github.com/llvm-mirror/libcxx/blob/master/include/experimental/any#L129
Показывает, что libС++ (clang's) дает вам 3 указателя void, стоящие на пробел, (24 байта, если они имеют ширину 8 байтов)
libstdС++ только один указатель:
https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/experimental/any?view=markup#l106
Изменение any
, чтобы сделать параметр шаблона не сложным, просто убедитесь, что существует возможность конвертирования между any
разных размеров.
IMO, разница в производительности настолько существенна между оптимизацией небольшого размера и распределением кучи в соответствии с моими критериями и стоимостью реализации, чтобы сделать его настолько малым, что он станет частью стандартного