New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Call for comments: make EnTT allocator-aware #22
Comments
First consideration: EnTT is focused on performances Introducing an interface with virtual methods sounds a bit against point one (opinion based), so I would like the first approach proposed (introduce a new template parameter). |
As a side point: std::allocator's interface was not made to encapsulate allocation algorithms, but to hide near/far pointers that existed in 1993. So if you want an allocator, you might consider an entirely different interface as well. |
@lessness @tazio |
On second thought, not injecting the registry with the allocator struct info is possible only if you introduce a global class/object, and if the registry uses it internally to retrieve the allocators. This does not require a full redesign, but involves a lot of rewriting; I don't know whether this is an appropriate solution. |
@lessness |
That given, I would go for injecting directly the registry. |
hi guys, sorry for the late reply. class Allocator {
public:
virtual void *allocate(size_t size, size_t align) = 0;
virtual void deallocate(void *p) = 0;
} Also, we should keep in mind that most of the cost of allocating memory is in the OS side, for synchronization etc, so the table lookup will not add much to that. Keep up with the great job, this library is getting better every day! |
As far as I can see, what you suggest is a breaking change.
Am I wrong? Furthermore, a journey along this path suggests that Thoughts? |
I am not an advanced c++ developer. And i (still) have not a real experience with EnTT. So In this moment I would not be affected by breaking changes. I must admit i like very, very, very much the header-only feature. Simplify things a lot and it makes portabily easier. I prefer small and perfect gems that humongous and super-general beasts (I'm looking at you, Boost). In fact I collect those gems. And that's how I discovered, EnTT!! (the header-only feature). :-D In my humble opinión the only valid reason to give up that feature (header-only) is to improve performance significantly. On the other hand It seems dangerous to implement new-and-very-shiny-and-cool features before they are requested by genuine use cases (similar to premature optimization). However perhaps i miss the global overview... DJuego P.S: I like the EnTT allocator-aware feature. 👍 It is interesting. |
@skypjack I was thinking about having the possibility to specify a different allocator for each component type; something on the line of an internal map type-allocator. The API could something similar to: registry.set_allocator<Transform>(my_custom_allocator); defaulting to a default allocator in case the user did not specify one for the given type. I don't consider this very high priority though; EnTT is quite fast already :) |
C++17 will not work for me (using C++14 is already pushing the boundaries of the compilers I have to support, unfortunately...) for a while. |
I added the request to the TODO file. I'm closing the issue because I've all the information I need to start working on it sooner or later. |
I'm taking a shot at adding allocator awareness to some of the files in the entity folder. So far all the tests still pass! |
@rilerez is your work publicly available? I've a pretty clear idea of what I'd like to do in this sense, even though I haven't done it yet. We can discuss your changes to see if they match eventually. |
I haven't pushed anything yet but I will push it to the experimental branch of my enTT fork. So far I have just been adding an optional |
Probably coming in a bit late here, but a nice scenario to support would be arena allocators that don't return memory incrementally but rather in one big reset thus avoid the expense of managing memory (and get better locality too since memory allocations won't be fragmented!). |
@philippecp A custom allocator you can set on a per-type basis will allow this. What's wrong with it? |
Hello! I have a use-case where I'd like to have EnTT allocate objects within a region of shared memory that is accessible via other processes. However, since I'm working with multiple blocks of shared memory, I've had to resort to a custom "fancy pointer" that encodes a block pointer C++17 seemed to formalize Allocator as a named requirement. This allows the allocator to provide the pointer type that a container implementation would use. For example: template <typename T>
struct my_allocator {
using pointer = block_pointer<T>;
// ...
}
template <typename T, typename Allocator = std::allocator<T>>
struct my_container {
using pointer = typename Allocator::pointer;
// Use `pointer` instead of `T*`
}
my_allocator allocator;
my_container<int, std::allocator_traits<my_allocator>> container(allocator); (Side note: you can also implement fancy pointers through So, from my perspective, the first step in making EnTT allocator-aware is to move away from using raw pointers and using the template<typename Entity, typename Type, typename Allocator = std::allocator<Type>, typename = void>
class basic_storage: public basic_sparse_set<Entity> {
template<typename Value>
class storage_iterator final {
...
public:
using value_type = Value;
using pointer = Allocator::pointer; // <-- Change from `value_type*` to `Allocator::pointer`
...
}
} I believe this approach would be compatible with Please let me know if there are any details you'd like for me to elaborate on. Thanks! |
@stefan-pdx maybe it's worth it to create a discussion for this. |
Thanks @skypjack! I'll follow up in a separate discussion. |
I was thinking about making
EnTT
allocator-aware. It's not the easiest task ever, but it could be an interesting feature.To do that, the first thing that comes to my mind is to add an extra template parameter to the registry that is propagated down to the internal data structures if required. Moreover, I would add a
reserve
function to the registry to pre-allocate enough space for components and entities.This way, users that don't want to deal with memory management can freely ignore the fact that
EnTT
is allocator-aware and let it use anstd::allocator
as it already does.The other solution around is to define an interface for allocators that offers a few virtual member functions, then pass an opaque instance to the constructor of the registry.
I don't like that much this approach, for it looks to me much more invasive than the other one.
If anyone out there is listening, every comment is welcome as usual.
The text was updated successfully, but these errors were encountered: