boost::any / std::any 是否就地存储小对象?
Does boost::any / std::any store small objects in-place?
要容纳任意大的对象,boost::any
/ std::any
肯定需要为对象分配堆 space。但是,对于大小小于或等于指针 (int,char,bool,...
) 的小型类型,any
可以将值就地存储在指针槽或其他一些就地内存中,而不分配堆space。但是实现会这样做吗?
我有一个场景,我经常将小类型存储在 any
中,有时只存储大类型,如 string
s。代码很热,因此我要问这个问题。如果不执行优化,我可能会更好地使用自己的实现来存储小类型。
无法保证,但 C++17 草案在 [any.class] 中声明
Implementations should avoid the use of dynamically allocated memory for a small contained object. [ Example: where the object constructed is holding only an int. — end example ] Such small-object optimization shall only be applied to types T
for which is_nothrow_move_constructible_v<T>
is true
.
不幸的是,它没有给出应该考虑什么的建议 small 除了说 int
应该能够存储在适当的位置。
如果我正确理解 Boost.Any 源代码,并在调试器中查看它,它不会应用小对象优化。 (注意无条件使用new。)
template<typename ValueType>
any(const ValueType & value)
: content(new holder<
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
>(value))
{
}
Nathan Oliver 和 Josh 的 Kelley 的回答是正确的:不能保证,boost 不使用小值优化。
在更实际的情况下,
https://github.com/llvm-mirror/libcxx/blob/master/include/experimental/any#L129
向您展示 libc++(clang 的)为您提供了 3 个价值 space 的空指针,(如果它们的宽度为 8 个字节,则为 24 个字节)
libstdc++只有一个指针:
https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/experimental/any?view=markup#l106
更改 any
使大小成为模板参数并不困难,只是您还应确保不同大小的 any
之间存在可转换性。
IMO,根据我的基准测试,小尺寸优化和堆分配之间的性能差异如此之大,而且将其制作成如此小的模板的实现成本将成为标准的一部分
要容纳任意大的对象,boost::any
/ std::any
肯定需要为对象分配堆 space。但是,对于大小小于或等于指针 (int,char,bool,...
) 的小型类型,any
可以将值就地存储在指针槽或其他一些就地内存中,而不分配堆space。但是实现会这样做吗?
我有一个场景,我经常将小类型存储在 any
中,有时只存储大类型,如 string
s。代码很热,因此我要问这个问题。如果不执行优化,我可能会更好地使用自己的实现来存储小类型。
无法保证,但 C++17 草案在 [any.class] 中声明
Implementations should avoid the use of dynamically allocated memory for a small contained object. [ Example: where the object constructed is holding only an int. — end example ] Such small-object optimization shall only be applied to types
T
for whichis_nothrow_move_constructible_v<T>
istrue
.
不幸的是,它没有给出应该考虑什么的建议 small 除了说 int
应该能够存储在适当的位置。
如果我正确理解 Boost.Any 源代码,并在调试器中查看它,它不会应用小对象优化。 (注意无条件使用new。)
template<typename ValueType>
any(const ValueType & value)
: content(new holder<
BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type
>(value))
{
}
Nathan Oliver 和 Josh 的 Kelley 的回答是正确的:不能保证,boost 不使用小值优化。
在更实际的情况下, https://github.com/llvm-mirror/libcxx/blob/master/include/experimental/any#L129 向您展示 libc++(clang 的)为您提供了 3 个价值 space 的空指针,(如果它们的宽度为 8 个字节,则为 24 个字节)
libstdc++只有一个指针: https://gcc.gnu.org/viewcvs/gcc/trunk/libstdc%2B%2B-v3/include/experimental/any?view=markup#l106
更改 any
使大小成为模板参数并不困难,只是您还应确保不同大小的 any
之间存在可转换性。
IMO,根据我的基准测试,小尺寸优化和堆分配之间的性能差异如此之大,而且将其制作成如此小的模板的实现成本将成为标准的一部分