shrink sizeof(array)

This commit is contained in:
Vinnie Falco 2019-11-12 09:18:39 -08:00
parent 8102e7b325
commit 7e7236609b
5 changed files with 397 additions and 137 deletions

View File

@ -450,10 +450,10 @@ main(
vi.emplace_back(new boost_default_impl);
vi.emplace_back(new boost_impl);
vi.emplace_back(new rapidjson_impl);
//vi.emplace_back(new nlohmann_impl);
vi.emplace_back(new nlohmann_impl);
benchParse(vs, vi);
//benchSerialize(vs, vi);
benchSerialize(vs, vi);
}
catch(system_error const& se)
{

View File

@ -12,40 +12,272 @@
[/-----------------------------------------------------------------------------]
[table
[ [Small Document] [Large Document] ]
[[
```
Boost.JSON parse 55952763 bytes in 234ms
Boost.JSON parse 55952763 bytes in 232ms
Boost.JSON parse 55952763 bytes in 231ms
rapidjson parse 55952763 bytes in 239ms
rapidjson parse 55952763 bytes in 240ms
rapidjson parse 55952763 bytes in 239ms
nlohmann parse 55952763 bytes in 495ms
nlohmann parse 55952763 bytes in 491ms
nlohmann parse 55952763 bytes in 494ms
tao-json parse 55952763 bytes in 2178ms
tao-json parse 55952763 bytes in 2069ms
tao-json parse 55952763 bytes in 2056ms
Parse File 1 array.json (609414 bytes)
boost(default): 530ms
boost(default): 488ms
boost(default): 465ms
boost(default): 483ms
boost(default): 478ms
boost(block): 453ms
boost(block): 456ms
boost(block): 455ms
boost(block): 454ms
boost(block): 455ms
rapidjson: 383ms
rapidjson: 383ms
rapidjson: 384ms
rapidjson: 382ms
rapidjson: 384ms
nlohmann: 1297ms
nlohmann: 1301ms
nlohmann: 1297ms
nlohmann: 1298ms
nlohmann: 1300ms
Parse File 2 arrays.json (1461524 bytes)
boost(default): 1301ms
boost(default): 1303ms
boost(default): 1304ms
boost(default): 1299ms
boost(default): 1304ms
boost(block): 956ms
boost(block): 954ms
boost(block): 956ms
boost(block): 955ms
boost(block): 955ms
rapidjson: 799ms
rapidjson: 790ms
rapidjson: 798ms
rapidjson: 799ms
rapidjson: 797ms
nlohmann: 2491ms
nlohmann: 2498ms
nlohmann: 2502ms
nlohmann: 2498ms
nlohmann: 2501ms
Parse File 3 strings.json (1016132 bytes)
boost(default): 96ms
boost(default): 96ms
boost(default): 97ms
boost(default): 95ms
boost(default): 96ms
boost(block): 50ms
boost(block): 48ms
boost(block): 49ms
boost(block): 48ms
boost(block): 49ms
rapidjson: 469ms
rapidjson: 467ms
rapidjson: 468ms
rapidjson: 470ms
rapidjson: 469ms
nlohmann: 939ms
nlohmann: 940ms
nlohmann: 937ms
nlohmann: 937ms
nlohmann: 938ms
Parse File 4 twitter.json (646995 bytes)
boost(default): 784ms
boost(default): 776ms
boost(default): 781ms
boost(default): 775ms
boost(default): 777ms
boost(block): 421ms
boost(block): 422ms
boost(block): 422ms
boost(block): 421ms
boost(block): 422ms
rapidjson: 477ms
rapidjson: 475ms
rapidjson: 484ms
rapidjson: 475ms
rapidjson: 488ms
nlohmann: 1535ms
nlohmann: 1551ms
nlohmann: 1539ms
nlohmann: 1534ms
nlohmann: 1529ms
Parse File 5 citm_catalog.json (1777672 bytes)
boost(default): 1748ms
boost(default): 1736ms
boost(default): 1742ms
boost(default): 1740ms
boost(default): 1734ms
boost(block): 1026ms
boost(block): 1025ms
boost(block): 1025ms
boost(block): 1041ms
boost(block): 1023ms
rapidjson: 908ms
rapidjson: 909ms
rapidjson: 908ms
rapidjson: 908ms
rapidjson: 909ms
nlohmann: 3597ms
nlohmann: 3586ms
nlohmann: 3585ms
nlohmann: 3587ms
nlohmann: 3589ms
Parse File 6 canada.json (2251060 bytes)
boost(default): 3343ms
boost(default): 3366ms
boost(default): 3359ms
boost(default): 3389ms
boost(default): 3416ms
boost(block): 2377ms
boost(block): 2373ms
boost(block): 2379ms
boost(block): 2377ms
boost(block): 2372ms
rapidjson: 1461ms
rapidjson: 1457ms
rapidjson: 1462ms
rapidjson: 1460ms
rapidjson: 1461ms
nlohmann: 13899ms
nlohmann: 13914ms
nlohmann: 13864ms
nlohmann: 13929ms
nlohmann: 13908ms
Serialize File 1 array.json (609414 bytes)
boost(default): 321ms
boost(default): 324ms
boost(default): 322ms
boost(default): 323ms
boost(default): 323ms
boost(block): 323ms
boost(block): 323ms
boost(block): 322ms
boost(block): 324ms
boost(block): 324ms
rapidjson: 794ms
rapidjson: 794ms
rapidjson: 793ms
rapidjson: 794ms
rapidjson: 793ms
nlohmann: 890ms
nlohmann: 889ms
nlohmann: 890ms
nlohmann: 889ms
nlohmann: 890ms
Serialize File 2 arrays.json (1461524 bytes)
boost(default): 1631ms
boost(default): 1629ms
boost(default): 1629ms
boost(default): 1625ms
boost(default): 1622ms
boost(block): 1599ms
boost(block): 1596ms
boost(block): 1601ms
boost(block): 1600ms
boost(block): 1598ms
rapidjson: 3134ms
rapidjson: 3147ms
rapidjson: 3135ms
rapidjson: 3137ms
rapidjson: 3139ms
nlohmann: 5173ms
nlohmann: 5165ms
nlohmann: 5152ms
nlohmann: 5146ms
nlohmann: 5182ms
Serialize File 3 strings.json (1016132 bytes)
boost(default): 597ms
boost(default): 598ms
boost(default): 596ms
boost(default): 597ms
boost(default): 597ms
boost(block): 578ms
boost(block): 577ms
boost(block): 578ms
boost(block): 579ms
boost(block): 583ms
rapidjson: 2097ms
rapidjson: 2094ms
rapidjson: 2095ms
rapidjson: 2094ms
rapidjson: 2096ms
nlohmann: 6790ms
nlohmann: 6781ms
nlohmann: 6799ms
nlohmann: 6785ms
nlohmann: 6793ms
Serialize File 4 twitter.json (646995 bytes)
boost(default): 664ms
boost(default): 627ms
boost(default): 647ms
boost(default): 627ms
boost(default): 626ms
boost(block): 613ms
boost(block): 616ms
boost(block): 611ms
boost(block): 611ms
boost(block): 623ms
rapidjson: 937ms
rapidjson: 898ms
rapidjson: 889ms
rapidjson: 895ms
rapidjson: 884ms
nlohmann: 1931ms
nlohmann: 1932ms
nlohmann: 1932ms
nlohmann: 1931ms
nlohmann: 1931ms
Serialize File 5 citm_catalog.json (1777672 bytes)
boost(default): 1022ms
boost(default): 1026ms
boost(default): 1101ms
boost(default): 1022ms
boost(default): 1022ms
boost(block): 939ms
boost(block): 940ms
boost(block): 936ms
boost(block): 943ms
boost(block): 938ms
rapidjson: 917ms
rapidjson: 952ms
rapidjson: 926ms
rapidjson: 929ms
rapidjson: 989ms
nlohmann: 1718ms
nlohmann: 1711ms
nlohmann: 1713ms
nlohmann: 1713ms
nlohmann: 1711ms
Serialize File 6 canada.json (2251060 bytes)
boost(default): 8551ms
boost(default): 8342ms
boost(default): 8307ms
boost(default): 8309ms
boost(default): 8284ms
boost(block): 8141ms
boost(block): 8093ms
boost(block): 8062ms
boost(block): 8065ms
boost(block): 8060ms
rapidjson: 10897ms
rapidjson: 10865ms
rapidjson: 10863ms
rapidjson: 10863ms
rapidjson: 10863ms
nlohmann: 16113ms
nlohmann: 16040ms
nlohmann: 15847ms
nlohmann: 15839ms
nlohmann: 15808ms
```
][
```
Boost.JSON parse 488889121 bytes in 1820ms
Boost.JSON parse 488889121 bytes in 1831ms
Boost.JSON parse 488889121 bytes in 1835ms
rapidjson parse 488889121 bytes in 1860ms
rapidjson parse 488889121 bytes in 1886ms
rapidjson parse 488889121 bytes in 1828ms
nlohmann parse 488889121 bytes in 4195ms
nlohmann parse 488889121 bytes in 4241ms
nlohmann parse 488889121 bytes in 4320ms
tao-json parse 488889121 bytes in 22952ms
tao-json parse 488889121 bytes in 23265ms
tao-json parse 488889121 bytes in 23117ms
```
]]
]
[/-----------------------------------------------------------------------------]

View File

@ -176,7 +176,7 @@ public:
*/
~array()
{
if( impl_.begin() &&
if( impl_.data() &&
sp_->need_free())
destroy();
}
@ -1592,9 +1592,13 @@ private:
class impl_type
{
value* vec_ = nullptr;
std::uint32_t size_ = 0;
std::uint32_t capacity_ = 0;
struct table
{
std::uint32_t size;
std::uint32_t capacity;
};
table* tab_ = nullptr;
public:
impl_type() = default;
@ -1614,31 +1618,39 @@ private:
inline
value*
begin() const noexcept
data() const noexcept
{
return vec_;
return tab_ ?
reinterpret_cast<
value*>(tab_ + 1) :
nullptr;
}
inline
std::size_t
size() const noexcept
{
return size_;
return tab_ ?
tab_->size : 0;
}
inline
void
size(std::size_t n) noexcept
{
size_ = static_cast<
std::uint32_t>(n);
if(tab_)
tab_->size = static_cast<
std::uint32_t>(n);
else
BOOST_JSON_ASSERT(n == 0);
}
inline
std::size_t
capacity() const noexcept
{
return capacity_;
return tab_ ?
tab_->capacity : 0;
}
inline
@ -1653,6 +1665,10 @@ private:
void
swap(impl_type& rhs) noexcept;
inline
void
destroy_impl(storage_ptr const& sp) noexcept;
BOOST_JSON_DECL
void
destroy(storage_ptr const& sp) noexcept;

View File

@ -50,7 +50,7 @@ index_of(value const* pos) const noexcept ->
std::size_t
{
return static_cast<
std::size_t>(pos - vec_);
std::size_t>(pos - data());
}
//----------------------------------------------------------
@ -120,7 +120,7 @@ at(std::size_t pos) ->
BOOST_JSON_THROW(
std::out_of_range(
"bad array index"));
return impl_.begin()[pos];
return impl_.data()[pos];
}
auto
@ -132,7 +132,7 @@ at(std::size_t pos) const ->
BOOST_JSON_THROW(
std::out_of_range(
"bad array index"));
return impl_.begin()[pos];
return impl_.data()[pos];
}
auto
@ -140,7 +140,7 @@ array::
operator[](std::size_t pos) noexcept ->
reference
{
return impl_.begin()[pos];
return impl_.data()[pos];
}
auto
@ -148,7 +148,7 @@ array::
operator[](std::size_t pos) const noexcept ->
const_reference
{
return impl_.begin()[pos];
return impl_.data()[pos];
}
auto
@ -156,7 +156,7 @@ array::
front() noexcept ->
reference
{
return *impl_.begin();
return *impl_.data();
}
auto
@ -164,7 +164,7 @@ array::
front() const noexcept ->
const_reference
{
return *impl_.begin();
return *impl_.data();
}
auto
@ -172,7 +172,7 @@ array::
back() noexcept ->
reference
{
return impl_.begin()[impl_.size() - 1];
return impl_.data()[impl_.size() - 1];
}
auto
@ -180,7 +180,7 @@ array::
back() const noexcept ->
const_reference
{
return impl_.begin()[impl_.size() - 1];
return impl_.data()[impl_.size() - 1];
}
auto
@ -188,7 +188,7 @@ array::
data() noexcept ->
value*
{
return impl_.begin();
return impl_.data();
}
auto
@ -196,7 +196,7 @@ array::
data() const noexcept ->
value const*
{
return impl_.begin();
return impl_.data();
}
//----------------------------------------------------------
@ -210,7 +210,7 @@ array::
begin() noexcept ->
iterator
{
return impl_.begin();
return impl_.data();
}
auto
@ -218,7 +218,7 @@ array::
begin() const noexcept ->
const_iterator
{
return impl_.begin();
return impl_.data();
}
auto
@ -226,7 +226,7 @@ array::
cbegin() const noexcept ->
const_iterator
{
return impl_.begin();
return impl_.data();
}
auto
@ -234,7 +234,7 @@ array::
end() noexcept ->
iterator
{
return impl_.begin() + impl_.size();
return impl_.data() + impl_.size();
}
auto
@ -242,7 +242,7 @@ array::
end() const noexcept ->
const_iterator
{
return impl_.begin() + impl_.size();
return impl_.data() + impl_.size();
}
auto
@ -250,7 +250,7 @@ array::
cend() const noexcept ->
const_iterator
{
return impl_.begin() + impl_.size();
return impl_.data() + impl_.size();
}
auto
@ -259,7 +259,7 @@ rbegin() noexcept ->
reverse_iterator
{
return reverse_iterator(
impl_.begin() + impl_.size());
impl_.data() + impl_.size());
}
auto
@ -268,7 +268,7 @@ rbegin() const noexcept ->
const_reverse_iterator
{
return const_reverse_iterator(
impl_.begin() + impl_.size());
impl_.data() + impl_.size());
}
auto
@ -277,7 +277,7 @@ crbegin() const noexcept ->
const_reverse_iterator
{
return const_reverse_iterator(
impl_.begin() + impl_.size());
impl_.data() + impl_.size());
}
auto
@ -286,7 +286,7 @@ rend() noexcept ->
reverse_iterator
{
return reverse_iterator(
impl_.begin());
impl_.data());
}
auto
@ -295,7 +295,7 @@ rend() const noexcept ->
const_reverse_iterator
{
return const_reverse_iterator(
impl_.begin());
impl_.data());
}
auto
@ -304,7 +304,7 @@ crend() const noexcept ->
const_reverse_iterator
{
return const_reverse_iterator(
impl_.begin());
impl_.data());
}
//----------------------------------------------------------
@ -356,7 +356,7 @@ emplace(
undo_insert u(pos, 1, *this);
u.emplace(std::forward<Arg>(arg));
u.commit = true;
return impl_.begin() + u.pos;
return impl_.data() + u.pos;
}
template<class Arg>
@ -367,7 +367,7 @@ emplace_back(Arg&& arg) ->
{
reserve(impl_.size() + 1);
auto& v = *::new(
impl_.begin() + impl_.size()) value(
impl_.data() + impl_.size()) value(
std::forward<Arg>(arg), sp_);
impl_.size(impl_.size() + 1);
return v;
@ -392,7 +392,7 @@ array(
{
if(impl_.size() >= impl_.capacity())
reserve(impl_.size() + 1);
::new(impl_.begin() + impl_.size()) value(
::new(impl_.data() + impl_.size()) value(
*first++, sp_);
impl_.size(impl_.size() + 1);
}
@ -418,7 +418,7 @@ array(
while(impl_.size() < n)
{
::new(
impl_.begin() +
impl_.data() +
impl_.size()) value(
*first++, sp_);
impl_.size(impl_.size() + 1);
@ -436,17 +436,17 @@ insert(
iterator
{
if(first == last)
return impl_.begin() +
return impl_.data() +
impl_.index_of(pos);
array tmp(first, last, sp_);
undo_insert u(
pos, tmp.impl_.size(), *this);
relocate(u.it,
tmp.impl_.begin(), tmp.impl_.size());
tmp.impl_.data(), tmp.impl_.size());
// don't destroy values in tmp
tmp.impl_.size(0);
u.commit = true;
return impl_.begin() + u.pos;
return impl_.data() + u.pos;
}
template<class InputIt>
@ -469,7 +469,7 @@ insert(
while(first != last)
u.emplace(*first++);
u.commit = true;
return begin() + u.pos;
return data() + u.pos;
}
} // json

View File

@ -35,27 +35,32 @@ impl_type(
BOOST_JSON_THROW(
detail::array_too_large_exception());
if(capacity > 0)
vec_ = reinterpret_cast<value*>(
sp->allocate(
capacity * sizeof(value),
alignof(value)));
{
tab_ = ::new(sp->allocate(
(sizeof(table) +
capacity * sizeof(value) +
sizeof(table) + 1)
/ sizeof(table)
* sizeof(table),
std::max(
alignof(table),
alignof(value)))) table;
tab_->capacity = static_cast<
std::uint32_t>(capacity);
tab_->size = 0;
}
else
vec_ = nullptr;
capacity_ = static_cast<
std::uint32_t>(capacity);
size_ = 0;
{
tab_ = nullptr;
}
}
array::
impl_type::
impl_type(impl_type&& other) noexcept
: vec_(detail::exchange(
other.vec_, nullptr))
, size_(detail::exchange(
other.size_, 0))
, capacity_(detail::exchange(
other.capacity_, 0))
: tab_(detail::exchange(
other.tab_, nullptr))
{
}
@ -71,15 +76,34 @@ operator=(
return *this;
}
void
array::
impl_type::
swap(impl_type& rhs) noexcept
{
std::swap(vec_, rhs.vec_);
std::swap(size_, rhs.size_);
std::swap(capacity_, rhs.capacity_);
auto tmp = tab_;
tab_ = rhs.tab_;
rhs.tab_ = tmp;
}
void
array::
impl_type::
destroy_impl(
storage_ptr const& sp) noexcept
{
auto it = data() + tab_->size;
while(it != data())
(*--it).~value();
sp->deallocate(tab_,
(sizeof(table) +
capacity() * sizeof(value) +
sizeof(table) + 1)
/ sizeof(table)
* sizeof(table),
std::max(
alignof(table),
alignof(value)));
}
void
@ -88,15 +112,8 @@ impl_type::
destroy(
storage_ptr const& sp) noexcept
{
if(vec_ && sp->need_free())
{
auto it = vec_ + size_;
while(it != vec_)
(*--it).~value();
sp->deallocate(vec_,
capacity_ * sizeof(value),
alignof(value));
}
if(tab_ && sp->need_free())
destroy_impl(sp);
}
//----------------------------------------------------------
@ -127,7 +144,7 @@ undo_insert(
self_.reserve(
self_.impl_.size() + n_);
// (iterators invalidated now)
it = self_.impl_.begin() + pos;
it = self_.impl_.data() + pos;
relocate(it + n_, it,
self_.impl_.size() - pos);
self_.impl_.size(
@ -141,7 +158,7 @@ undo_insert::
if(! commit)
{
auto const first =
self_.impl_.begin() + pos;
self_.impl_.data() + pos;
self_.destroy(first, it);
self_.impl_.size(
self_.impl_.size() - n_);
@ -175,7 +192,7 @@ array(
while(impl_.size() < count)
{
::new(
impl_.begin() +
impl_.data() +
impl_.size()) value(v, sp_);
impl_.size(impl_.size() + 1);
}
@ -193,7 +210,7 @@ array(
while(impl_.size() < count)
{
::new(
impl_.begin() +
impl_.data() +
impl_.size()) value(sp_);
impl_.size(impl_.size() + 1);
}
@ -270,7 +287,7 @@ array(unchecked_array&& ua)
, impl_(ua.size(), sp_) // exact
{
impl_.size(ua.size());
ua.relocate(impl_.begin());
ua.relocate(impl_.data());
}
//----------------------------------------------------------
@ -336,8 +353,8 @@ shrink_to_fit() noexcept
#endif
impl_type impl(impl_.size(), sp_);
relocate(
impl.begin(),
impl_.begin(), impl_.size());
impl.data(),
impl_.data(), impl_.size());
impl.size(impl_.size());
impl_.size(0);
impl_.swap(impl);
@ -362,10 +379,10 @@ void
array::
clear() noexcept
{
if(! impl_.begin())
if(! impl_.data())
return;
destroy(impl_.begin(),
impl_.begin() + impl_.size());
destroy(impl_.data(),
impl_.data() + impl_.size());
impl_.size(0);
}
@ -381,7 +398,7 @@ insert(
while(count--)
u.emplace(v);
u.commit = true;
return impl_.begin() + u.pos;
return impl_.data() + u.pos;
}
auto
@ -397,7 +414,7 @@ insert(
for(auto const& v : init)
u.emplace(v);
u.commit = true;
return impl_.begin() + u.pos;
return impl_.data() + u.pos;
}
auto
@ -406,8 +423,8 @@ erase(
const_iterator pos) noexcept ->
iterator
{
auto p = impl_.begin() +
(pos - impl_.begin());
auto p = impl_.data() +
(pos - impl_.data());
destroy(p, p + 1);
relocate(p, p + 1, 1);
impl_.size(impl_.size() - 1);
@ -424,7 +441,7 @@ erase(
auto const n = static_cast<
std::size_t>(last - first);
auto const p =
impl_.begin() + impl_.index_of(first);
impl_.data() + impl_.index_of(first);
destroy(p, p + n);
relocate(p, p + n,
impl_.size() -
@ -449,17 +466,17 @@ resize(std::size_t count)
if(count <= impl_.size())
{
destroy(
impl_.begin() + count,
impl_.begin() + impl_.size());
impl_.data() + count,
impl_.data() + impl_.size());
impl_.size(count);
return;
}
reserve(count);
auto it =
impl_.begin() + impl_.size();
impl_.data() + impl_.size();
auto const end =
impl_.begin() + count;
impl_.data() + count;
while(it != end)
::new(it++) value(sp_);
impl_.size(count);
@ -474,8 +491,8 @@ resize(
if(count <= size())
{
destroy(
impl_.begin() + count,
impl_.begin() + impl_.size());
impl_.data() + count,
impl_.data() + impl_.size());
impl_.size(count);
return;
}
@ -496,10 +513,10 @@ resize(
};
auto const end =
impl_.begin() + count;
impl_.data() + count;
undo u{*this,
impl_.begin() + impl_.size(),
impl_.begin() + impl_.size()};
impl_.data() + impl_.size(),
impl_.data() + impl_.size()};
do
{
::new(u.it) value(v, sp_);
@ -548,12 +565,7 @@ void
array::
destroy() noexcept
{
auto it = impl_.begin() + impl_.size();
while(it != impl_.begin())
(*--it).~value();
sp_->deallocate(impl_.begin(),
impl_.capacity() * sizeof(value),
alignof(value));
impl_.destroy_impl(sp_);
}
void
@ -564,7 +576,7 @@ copy(array const& other)
for(auto const& v : other)
{
::new(
impl_.begin() +
impl_.data() +
impl_.size()) value(v, sp_);
impl_.size(impl_.size() + 1);
}
@ -584,7 +596,7 @@ copy(
for(auto const& v : init)
{
::new(
impl_.begin() +
impl_.data() +
impl_.size()) value(v, sp_);
impl_.size(impl_.size() + 1);
}
@ -594,7 +606,7 @@ void
array::
reserve_impl(std::size_t capacity)
{
if(impl_.begin())
if(impl_.data())
{
// 2x growth
auto const hint =
@ -608,8 +620,8 @@ reserve_impl(std::size_t capacity)
capacity = min_capacity_;
impl_type impl(capacity, sp_);
relocate(
impl.begin(),
impl_.begin(), impl_.size());
impl.data(),
impl_.data(), impl_.size());
impl.size(impl_.size());
impl_.size(0);
impl_.destroy(sp_);