Сохраняет ли boost::any / std::any маленькие объекты на месте?

Держать сколь угодно большие объекты, boost::any / std::any безусловно, необходимо выделить пространство кучи для объектов. Тем не менее, для небольших типов, размер которых меньше или равен указателю (int,char,bool,...), any вместо этого можно хранить значение на месте в слоте указателя или в какой-либо другой памяти на месте и не выделять пространство кучи. Но реализация делает это?

У меня есть сценарий, где я часто храню мелкие типы в any и только иногда более крупные типы, такие как strings. Код довольно горячий, и поэтому я задаю вопрос. Если оптимизация не будет выполнена, мне может быть лучше иметь собственную реализацию, которая хранит мелкие типы на месте.

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, разница в производительности настолько существенная между оптимизацией небольшого размера и выделением кучи, согласно моим оценкам, и стоимостью внедрения такого маленького шаблона, который станет частью стандарта.

Другие вопросы по тегам