config: ENTT_PAGE_SIZE sets the number of elements of a page, not the size in bytes

This commit is contained in:
Michele Caini
2021-02-25 00:18:04 +01:00
parent c3f7f83c55
commit 2222e31885
4 changed files with 31 additions and 30 deletions

View File

@@ -62,10 +62,10 @@ default type if necessary.
## ENTT_PAGE_SIZE
As is known, the ECS module of `EnTT` is based on _sparse sets_. What is less
known perhaps is that these are paged to reduce memory consumption in some
corner cases.<br/>
The default size of a page is 16kB but users can adjust it if appropriate. In
all case, the chosen value **must** be a power of 2.
known perhaps is that these are paged to reduce memory consumption.<br/>
Default size of pages (that is, the number of elements they contain) is 4096 but
users can adjust it if appropriate. In all case, the chosen value **must** be a
power of 2.
## ENTT_ASSERT

View File

@@ -21,8 +21,10 @@
#endif
#ifndef ENTT_PAGE_SIZE
# define ENTT_PAGE_SIZE 16384
#ifdef ENTT_PAGE_SIZE
static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0), "ENTT_PAGE_SIZE must be a power of two");
#else
# define ENTT_PAGE_SIZE 4096
#endif

View File

@@ -41,8 +41,7 @@ namespace entt {
*/
template<typename Entity>
class basic_sparse_set {
static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0), "ENTT_PAGE_SIZE must be a power of two");
static constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(Entity);
static constexpr auto page_size = ENTT_PAGE_SIZE;
using traits_type = entt_traits<Entity>;
using page_type = std::unique_ptr<Entity[]>;
@@ -150,11 +149,11 @@ class basic_sparse_set {
};
[[nodiscard]] auto page(const Entity entt) const ENTT_NOEXCEPT {
return size_type{(to_integral(entt) & traits_type::entity_mask) / entt_per_page};
return size_type{(to_integral(entt) & traits_type::entity_mask) / page_size};
}
[[nodiscard]] auto offset(const Entity entt) const ENTT_NOEXCEPT {
return size_type{to_integral(entt) & (entt_per_page - 1)};
return size_type{to_integral(entt) & (page_size - 1)};
}
[[nodiscard]] page_type & assure(const std::size_t pos) {
@@ -163,9 +162,9 @@ class basic_sparse_set {
}
if(!sparse[pos]) {
sparse[pos].reset(new entity_type[entt_per_page]);
sparse[pos].reset(new entity_type[page_size]);
// null is safe in all cases for our purposes
for(auto *first = sparse[pos].get(), *last = first + entt_per_page; first != last; ++first) {
for(auto *first = sparse[pos].get(), *last = first + page_size; first != last; ++first) {
*first = null;
}
}
@@ -245,7 +244,7 @@ public:
* @return Extent of the sparse set.
*/
[[nodiscard]] size_type extent() const ENTT_NOEXCEPT {
return sparse.size() * entt_per_page;
return sparse.size() * page_size;
}
/**

View File

@@ -85,34 +85,34 @@ TEST(SparseSet, Functionalities) {
TEST(SparseSet, Pagination) {
entt::sparse_set set;
constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(entt::entity);
constexpr auto page_size = ENTT_PAGE_SIZE;
ASSERT_EQ(set.extent(), 0u);
set.emplace(entt::entity{entt_per_page-1});
set.emplace(entt::entity{page_size-1});
ASSERT_EQ(set.extent(), entt_per_page);
ASSERT_TRUE(set.contains(entt::entity{entt_per_page-1}));
ASSERT_EQ(set.extent(), page_size);
ASSERT_TRUE(set.contains(entt::entity{page_size-1}));
set.emplace(entt::entity{entt_per_page});
set.emplace(entt::entity{page_size});
ASSERT_EQ(set.extent(), 2 * entt_per_page);
ASSERT_TRUE(set.contains(entt::entity{entt_per_page-1}));
ASSERT_TRUE(set.contains(entt::entity{entt_per_page}));
ASSERT_FALSE(set.contains(entt::entity{entt_per_page+1}));
ASSERT_EQ(set.extent(), 2 * page_size);
ASSERT_TRUE(set.contains(entt::entity{page_size-1}));
ASSERT_TRUE(set.contains(entt::entity{page_size}));
ASSERT_FALSE(set.contains(entt::entity{page_size+1}));
set.remove(entt::entity{entt_per_page-1});
set.remove(entt::entity{page_size-1});
ASSERT_EQ(set.extent(), 2 * entt_per_page);
ASSERT_FALSE(set.contains(entt::entity{entt_per_page-1}));
ASSERT_TRUE(set.contains(entt::entity{entt_per_page}));
ASSERT_EQ(set.extent(), 2 * page_size);
ASSERT_FALSE(set.contains(entt::entity{page_size-1}));
ASSERT_TRUE(set.contains(entt::entity{page_size}));
set.shrink_to_fit();
set.remove(entt::entity{entt_per_page});
set.remove(entt::entity{page_size});
ASSERT_EQ(set.extent(), 2 * entt_per_page);
ASSERT_FALSE(set.contains(entt::entity{entt_per_page-1}));
ASSERT_FALSE(set.contains(entt::entity{entt_per_page}));
ASSERT_EQ(set.extent(), 2 * page_size);
ASSERT_FALSE(set.contains(entt::entity{page_size-1}));
ASSERT_FALSE(set.contains(entt::entity{page_size}));
set.shrink_to_fit();