Do custom allocator apply just to containers, and how do i apply them to any memory allocation

https://en.cppreference.com/w/cpp/named_req/Allocator

I am referring to this ^^^^ kinds of custom of memory allocator (if there is a different kind of allocator let me know)

I am asking because I have a certain allocation and deallocation pattern where I do lot of allocations and then free them all at once (this pattern repeats many times),
and I am looking for a way to optimize away the alloc and free cost, and I am looking for what is the "proper" way to write that out

One possible solution (which I am leaning towards) is simply making a std::vector (which stores the objects)
and pushing in all the "new" objects and when I am done simply clearing the vector (aka marking the memory as unused)
The bigest downside from what i can tell using this method (which does not apply to my case) is that if you have objects of different sizes you can not use the same vector

A second solution would be to use a linear allocator from (https://github.com/mtrebi/memory-allocators) which acts similarly to the std::vector example as shown above

A third option (which is probably not a valid option because I misunderstand what an allocator is) is using a STL complaint allocator every time I am calling new

Here is a snippet of code to better understand my problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
	for ( 1000+ times){
		...
		for (many iter){
			...
			new some_object
			...//compute heavy stuff
		}
		... //other compute heavy stuff
		for (many iter){
			delete some_object
		}
	}
}

Lines 6 and 11 take up a large portion of total execution time



P.S. there is probably a better title for this question, if you have one let me know
Last edited on
If you need many objects of different types then you're not going to be able to optimize much. This is about the best you can hope for:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
size_t size = estimate_memory_requirements();
std::unique_ptr<char[]> mem(new char[size]);
char *next = mem.get();
for (auto &i : objects_to_allocate){
    auto p = next;
    i.pointer = p;
    next += i.size;
    i.constructor(); //calls placement new on pointer
    //compute heavy stuff
}

//other compute heavy stuff

//you can comment out this loop ONLY if destructors are trivial
for (auto &i : objects_to_allocate)
    i.destructor(); //calls destructor on pointer (NOT delete)

mem.reset();
How many different sized objects are we talking about here? If a few, then perhaps a memory pool for each object size?
Is it always the same objects, or does the mix of objects change between iterations?

If it is always the same set of objects, you could just create them once and then re-initialize them before each iteration. Tear them down just once at the end.

Another poster, @mitsuru, apparently had good luck applying some of the discussion in this thread:
https://www.cplusplus.com/forum/general/273999/
for my case i only have 1 object type (so same size always)
but i am asking incase there is a built in langauge construct to allow me to do that without resorting to manually writing the code my self


Edit i just found this out:
1
2
3
4
5
6
7
8
9
int main() {
	std::vector<int> v(10);
	alignas(int) std::byte buf[sizeof(int)];

	int* i = new(buf) int; //alocate starting at the address of  buf
	int* j = new(&v[0]) int; //alocate starting at the address of  buf
	assert((size_t)i == (size_t)buf);
	assert((size_t)j == (size_t)&v[0]);
}

which allows you to allocate in place
this is called new's placement parameters, more on: https://en.cppreference.com/w/cpp/language/new section 2.1.1
Last edited on
There's no point in aligning the vector.
Topic archived. No new replies allowed.