Skip to content

Commit

Permalink
performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Jul 28, 2017
1 parent a2b0a09 commit cc1419a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 134 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wconversion")
# set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-Wextra -Weffc++")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g -DDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DRELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -DRELEASE")

#
# CMake configuration
Expand Down
18 changes: 0 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,6 @@ int main() {
else { ecs.destroy(entity); }
}

std::cout << "filtered component view" << std::endl;

for(auto entity: ecs.view<Position>().exclude<Velocity>()) {
std::cout << (ecs.has<Position>(entity)) << "/" << (ecs.has<Velocity>(entity)) << std::endl;
}

ecs.reset();
}
```
Expand Down Expand Up @@ -223,7 +217,6 @@ There are three different kinds of view, each one with a slighlty different inte

* The _single component view_.
* The _multi component view_.
* The _filtered view_.

All of them are iterable. In other terms they have `begin` and `end` member functions that are suitable for a range-based for loop:

Expand Down Expand Up @@ -252,17 +245,6 @@ The multi component view has an additional member function:

* `reset()`: reorganizes internal data so as to further create optimized iterators (use it whenever the data within the registry are known to be changed).

A filtered view is nothing more than a multi component view with an additional set of components that act as filters.<br/>
Users can create filtered views either from a single component view or from a multi component view by means of the `exclude` member function:

```cpp
auto view = registry.view<Position>().exclude<Velocity>();

for(auto entity: view) {
// do whatever you want with your entities
}
```

All the views can be used more than once. They return newly created and correctly initialized iterators whenever
`begin` or `end` is invoked. Anyway views and iterators are tiny objects and the time to construct them can be safely ignored.
I'd suggest not to store them anywhere and to invoke the `Registry::view` member function at each iteration to get a properly
Expand Down
135 changes: 68 additions & 67 deletions src/registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,48 @@
#define ENTT_REGISTRY_HPP


#include <tuple>
#include <vector>
#include <bitset>
#include <utility>
#include <cstddef>
#include <iterator>
#include <cassert>
#include <type_traits>
#include "component_pool.hpp"
#include "ident.hpp"


/**
* TODO
*
* * bitmask nella view azzera il bit di validità, va bene?
* * invertire cammino su multiple, da 0 a size e non da size a 0
*/


namespace entt {


template<typename...>
class View;


template<template<typename...> class Pool, typename Entity, typename... Components, typename Type, typename... Types, typename... Filters>
class View<Pool<Entity, Components...>, std::tuple<Type, Types...>, std::tuple<Filters...>> final {
template<template<typename...> class Pool, typename Entity, typename... Components, typename Type, typename... Types>
class View<Pool<Entity, Components...>, Type, Types...> final {
using pool_type = Pool<Entity, Components...>;
using entity_type = typename pool_type::entity_type;
using mask_type = std::bitset<sizeof...(Components)+1>;

class ViewIterator;

public:
using iterator_type = ViewIterator;
using size_type = typename pool_type::size_type;

private:
class ViewIterator {
bool valid() const noexcept {
using accumulator_type = bool[];
auto &bitmask = mask[entities[pos-1]];
bool all = bitmask.test(ident<Components...>.template get<Type>());
accumulator_type types = { true, (all = all && bitmask.test(ident<Components...>.template get<Types>()))... };
accumulator_type filters = { true, (all = all && !bitmask.test(ident<Components...>.template get<Filters>()))... };
return void(types), void(filters), all;
inline bool valid() const noexcept {
return ((mask[entities[pos]] & bitmask) == bitmask);
}

public:
Expand All @@ -43,14 +53,15 @@ class View<Pool<Entity, Components...>, std::tuple<Type, Types...>, std::tuple<F
using pointer = entity_type *;
using iterator_category = std::input_iterator_tag;

ViewIterator(pool_type &pool, const entity_type *entities, typename pool_type::size_type pos, mask_type *mask) noexcept
: pool{pool}, entities{entities}, pos{pos}, mask{mask}
ViewIterator(const mask_type &bitmask, const entity_type *entities, const mask_type *mask, size_type pos, size_type last) noexcept
: bitmask{bitmask}, entities{entities}, mask{mask}, pos{pos}, last{last}
{
if(this->pos) { while(!valid() && --this->pos); }
while(this->pos != last && !valid()) { ++this->pos; }
}

ViewIterator & operator++() noexcept {
if(pos) { while(--pos && !valid()); }
++pos;
while(pos != last && !valid()) { ++pos; }
return *this;
}

Expand All @@ -60,22 +71,23 @@ class View<Pool<Entity, Components...>, std::tuple<Type, Types...>, std::tuple<F
}

bool operator==(const ViewIterator &other) const noexcept {
return other.entities == entities && other.pos == pos && other.mask == mask;
return other.pos == pos && other.entities == entities;
}

bool operator!=(const ViewIterator &other) const noexcept {
return !(*this == other);
}

value_type operator*() const noexcept {
return *(entities+pos-1);
return entities[pos];
}

private:
pool_type &pool;
const mask_type bitmask;
const entity_type *entities;
typename pool_type::size_type pos;
mask_type *mask;
const mask_type *mask;
size_type pos;
size_type last;
};

template<typename Comp>
Expand All @@ -89,34 +101,25 @@ class View<Pool<Entity, Components...>, std::tuple<Type, Types...>, std::tuple<F
}

public:
using iterator_type = ViewIterator;
using size_type = typename pool_type::size_type;

template<typename... Comp>
using view_type = View<pool_type, std::tuple<Type, Types...>, std::tuple<Comp...>>;

explicit View(pool_type &pool, mask_type *mask) noexcept
explicit View(const pool_type &pool, const mask_type *mask) noexcept
: entities{pool.template entities<Type>()},
size{pool.template size<Type>()},
pool{pool},
mask{mask}
mask{mask},
size{pool.template size<Type>()}
{
using accumulator_type = int[];
accumulator_type accumulator = { 0, (prefer<Types>(), 0)... };
(void)accumulator;
}

template<typename... Comp>
view_type<Comp...> exclude() noexcept {
return view_type<Comp...>{pool, mask};
bitmask.set(ident<Components...>.template get<Type>());
accumulator_type types = { 0, (bitmask.set(ident<Components...>.template get<Types>()), 0)... };
accumulator_type pref = { 0, (prefer<Types>(), 0)... };
(void)types, (void)pref;
}

iterator_type begin() const noexcept {
return ViewIterator{pool, entities, size, mask};
return ViewIterator{bitmask, entities, mask, 0, size};
}

iterator_type end() const noexcept {
return ViewIterator{pool, entities, 0, mask};
return ViewIterator{bitmask, entities, mask, size, size};
}

void reset() noexcept {
Expand All @@ -129,31 +132,38 @@ class View<Pool<Entity, Components...>, std::tuple<Type, Types...>, std::tuple<F

private:
const entity_type *entities;
const pool_type &pool;
const mask_type *mask;
size_type size;
pool_type &pool;
mask_type *mask;
mask_type bitmask;
};


template<template<typename...> class Pool, typename Entity, typename... Components, typename Type>
class View<Pool<Entity, Components...>, std::tuple<Type>, std::tuple<>> final {
class View<Pool<Entity, Components...>, Type> final {
using pool_type = Pool<Entity, Components...>;
using entity_type = typename pool_type::entity_type;
using mask_type = std::bitset<sizeof...(Components)+1>;

struct ViewIterator;

public:
using size_type = typename pool_type::size_type;
using iterator_type = ViewIterator;

private:
struct ViewIterator {
using value_type = entity_type;
using difference_type = std::ptrdiff_t;
using reference = entity_type &;
using pointer = entity_type *;
using iterator_category = std::input_iterator_tag;

ViewIterator(const entity_type *entities, typename pool_type::size_type pos) noexcept
ViewIterator(const entity_type *entities, size_type pos) noexcept
: entities{entities}, pos{pos}
{}

ViewIterator & operator++() noexcept {
--pos;
++pos;
return *this;
}

Expand All @@ -163,53 +173,41 @@ class View<Pool<Entity, Components...>, std::tuple<Type>, std::tuple<>> final {
}

bool operator==(const ViewIterator &other) const noexcept {
return other.entities == entities && other.pos == pos;
return other.pos == pos && other.entities == entities;
}

bool operator!=(const ViewIterator &other) const noexcept {
return !(*this == other);
}

value_type operator*() const noexcept {
return *(entities+pos-1);
return entities[pos];
}

private:
const entity_type *entities;
typename pool_type::size_type pos;
size_type pos;
};

public:
using iterator_type = ViewIterator;
using size_type = typename pool_type::size_type;

template<typename... Comp>
using view_type = View<pool_type, std::tuple<Type>, std::tuple<Comp...>>;

explicit View(pool_type &pool, mask_type *mask) noexcept
: pool{pool}, mask{mask}
explicit View(const pool_type &pool) noexcept
: pool{pool}
{}

template<typename... Comp>
view_type<Comp...> exclude() noexcept {
return view_type<Comp...>{pool, mask};
}

iterator_type begin() const noexcept {
return ViewIterator{pool.template entities<Type>(), pool.template size<Type>()};
return ViewIterator{pool.template entities<Type>(), 0};
}

iterator_type end() const noexcept {
return ViewIterator{pool.template entities<Type>(), 0};
return ViewIterator{pool.template entities<Type>(), pool.template size<Type>()};
}

size_type size() const noexcept {
return pool.template size<Type>();
}

private:
pool_type &pool;
mask_type *mask;
const pool_type &pool;
};


Expand Down Expand Up @@ -254,7 +252,7 @@ class Registry<Pool<Entity, Components...>> {

public:
template<typename... Comp>
using view_type = View<pool_type, std::tuple<Comp...>, std::tuple<>>;
using view_type = View<pool_type, Comp...>;

template<typename... Args>
Registry(Args&&... args)
Expand Down Expand Up @@ -416,9 +414,12 @@ class Registry<Pool<Entity, Components...>> {
}

template<typename... Comp>
view_type<Comp...> view() noexcept {
return view_type<Comp...>{pool, entities.data()};
}
std::enable_if_t<(sizeof...(Comp) == 1), view_type<Comp...>>
view() noexcept { return view_type<Comp...>{pool}; }

template<typename... Comp>
std::enable_if_t<(sizeof...(Comp) > 1), view_type<Comp...>>
view() noexcept { return view_type<Comp...>{pool, entities.data()}; }

private:
std::vector<mask_type> entities;
Expand Down
4 changes: 2 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ add_test(NAME ${TARGET_ENTT} COMMAND ${TARGET_ENTT})

# Test TARGET_BENCHMARK

IF(CMAKE_BUILD_TYPE MATCHES Release)
#IF(CMAKE_BUILD_TYPE MATCHES Release)
add_executable(${TARGET_BENCHMARK} benchmark.cpp)
target_include_directories(${TARGET_BENCHMARK} PRIVATE ${PROJECT_SRC_DIR})
target_link_libraries(${TARGET_BENCHMARK} PRIVATE ${COMMON_LINK_LIBS})
add_test(NAME ${TARGET_BENCHMARK} COMMAND ${TARGET_BENCHMARK})
ENDIF()
#ENDIF()
Loading

0 comments on commit cc1419a

Please sign in to comment.