Skip to content

Commit 6096047

Browse files
author
kelbon
committed
optimize align calculateion
1 parent 0d6a896 commit 6096047

File tree

4 files changed

+40
-16
lines changed

4 files changed

+40
-16
lines changed

include/kelcoro/common.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ struct retblock_storage {
3939

4040
namespace dd {
4141

42-
constexpr std::size_t hardware_constructive_interference_size = 64;
43-
constexpr std::size_t hardware_destructive_interference_size = 64;
42+
constexpr size_t hardware_constructive_interference_size = 64;
43+
constexpr size_t hardware_destructive_interference_size = 64;
4444

4545
struct not_movable {
4646
constexpr not_movable() noexcept = default;

include/kelcoro/memory_support.hpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <atomic>
4+
#include <bit>
45
#include <memory_resource>
56
#include <cassert>
67
#include <utility>
@@ -63,7 +64,7 @@ struct chunk_from {
6364
return std::assume_aligned<dd::coroframe_align()>(resource().allocate(sz));
6465
}
6566

66-
void deallocate(void* p, std::size_t sz) noexcept {
67+
void deallocate(void* p, size_t sz) noexcept {
6768
resource().deallocate(p, sz);
6869
}
6970
};
@@ -74,7 +75,7 @@ struct new_delete_resource {
7475
// not malloc because of memory alignment requirement
7576
return new char[sz];
7677
}
77-
static void deallocate(void* p, std::size_t) noexcept {
78+
static void deallocate(void* p, size_t) noexcept {
7879
delete[] static_cast<char*>(p);
7980
}
8081
};
@@ -120,7 +121,7 @@ struct polymorphic_resource {
120121
void* allocate(size_t sz) {
121122
return passed->allocate(sz, coroframe_align());
122123
}
123-
void deallocate(void* p, std::size_t sz) noexcept {
124+
void deallocate(void* p, size_t sz) noexcept {
124125
passed->deallocate(p, sz, coroframe_align());
125126
}
126127
};
@@ -176,6 +177,19 @@ constexpr size_t padding_len(size_t sz) noexcept {
176177
return (P - sz % P) % P;
177178
}
178179

180+
template <size_t ALIGN>
181+
constexpr size_t aligned(size_t size) {
182+
if constexpr (ALIGN < 2)
183+
return size;
184+
// is power of 2
185+
if constexpr (std::has_single_bit(ALIGN) == 1) {
186+
constexpr size_t mask = ALIGN - 1;
187+
return (size + mask) & ~mask;
188+
} else {
189+
return size + (ALIGN - size % ALIGN) % ALIGN;
190+
}
191+
}
192+
179193
} // namespace noexport
180194

181195
// inheritor(coroutine promise) may be allocated with 'R'
@@ -187,7 +201,7 @@ struct overload_new_delete {
187201
if constexpr (std::is_empty_v<R>)
188202
return (void*)r.allocate(frame_sz);
189203
else {
190-
frame_sz += noexport::padding_len<alignof(R)>(frame_sz);
204+
frame_sz = noexport::aligned<alignof(R)>(frame_sz);
191205
std::byte* p = (std::byte*)r.allocate(frame_sz + sizeof(R));
192206
new (p + frame_sz) R(std::move(r));
193207
return p;
@@ -204,20 +218,20 @@ struct overload_new_delete {
204218

205219
template <typename... Args>
206220
requires(last_is_memory_resource_tag<Args...> && std::is_same_v<R, resource_type_t<Args...>>)
207-
static void* operator new(std::size_t frame_sz, Args&&... args) {
221+
static void* operator new(size_t frame_sz, Args&&... args) {
208222
static_assert(std::is_same_v<std::remove_cvref_t<noexport::last_type_t<Args...>>, with_resource<R>>);
209223
// old-style
210224
// return do_allocate(frame_sz, (args...[sizeof...(Args) - 1]).resource);
211225
auto voidify = [](auto& x) { return const_cast<void*>((const void volatile*)std::addressof(x)); };
212226
void* p = (voidify(args), ...);
213227
return do_allocate(frame_sz, static_cast<with_resource<R>*>(p)->resource);
214228
}
215-
static void operator delete(void* ptr, std::size_t frame_sz) noexcept {
229+
static void operator delete(void* ptr, size_t frame_sz) noexcept {
216230
if constexpr (std::is_empty_v<R>) {
217231
R r{};
218232
r.deallocate(ptr, frame_sz);
219233
} else {
220-
frame_sz += noexport::padding_len<alignof(R)>(frame_sz);
234+
frame_sz = noexport::aligned<alignof(R)>(frame_sz);
221235
R* onframe_resource = (R*)((std::byte*)ptr + frame_sz);
222236
assert((((uintptr_t)onframe_resource % alignof(R)) == 0));
223237
if constexpr (std::is_trivially_destructible_v<R>) {

include/kelcoro/stack_memory_resource.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ struct stack_resource {
4545
}
4646

4747
chunk_header* take_atleast(size_t bytes) noexcept {
48-
size_t sz_before = count();
4948
chunk_header* prev = nullptr;
5049
chunk_header* c = top;
5150
while (c) {
@@ -55,8 +54,7 @@ struct stack_resource {
5554
prev->freelist_next = c->freelist_next;
5655
else
5756
top = c->freelist_next;
58-
c->freelist_next = nullptr;
59-
assert(count() == sz_before - 1);
57+
// not needed rly c->freelist_next = nullptr;
6058
return c;
6159
}
6260
prev = c;
@@ -107,7 +105,7 @@ struct stack_resource {
107105
freelist.push(chunk);
108106
}
109107

110-
std::size_t aligned(std::size_t bytes) {
108+
size_t aligned(size_t bytes) {
111109
return bytes + noexport::padding_len<dd::coroframe_align()>(bytes);
112110
}
113111

@@ -168,14 +166,14 @@ struct stack_resource {
168166
return b;
169167
}
170168

171-
void deallocate(void* ptr, size_t len) noexcept {
169+
void deallocate(const void* ptr, size_t len) noexcept {
172170
assert(((uintptr_t)ptr % 16) == 0 && "dealloc not allocated memory");
173171
len = aligned(len);
174172
// not in current chunk, must be in some of prev
175173
// in most cases its literaly previous chunk, but its possible
176174
// if all memory from chunk deallocated, then allocated > chunk size
177175
// so prev chunk will be empty
178-
while ((byte_t*)ptr != m - len) {
176+
while ((const byte_t*)ptr != m - len) {
179177
assert(ptr <= b || ptr >= e);
180178
drop_cur_chunk();
181179
}

tests/test_coroutines.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ inline dd::generator<int> foo() {
5050
struct r2 : dd::pmr::polymorphic_resource {};
5151

5252
TEST(allocations) {
53+
using dd::noexport::aligned;
5354
using dd::noexport::padding_len;
5455
static_assert(padding_len<16>(16) == 0);
5556
static_assert(padding_len<16>(0) == 0);
@@ -60,6 +61,15 @@ TEST(allocations) {
6061
static_assert(padding_len<4>(1) == 3);
6162
static_assert(padding_len<4>(4) == 0);
6263

64+
static_assert(aligned<16>(16) == 16);
65+
static_assert(aligned<16>(0) == 0);
66+
static_assert(aligned<16>(1) == 16);
67+
static_assert(aligned<16>(8) == 16);
68+
static_assert(aligned<4>(3) == 4);
69+
static_assert(aligned<4>(2) == 4);
70+
static_assert(aligned<4>(1) == 4);
71+
static_assert(aligned<4>(4) == 4);
72+
6373
#define EXPECT_PROMISE(promise, ... /* coro arg args*/) \
6474
static_assert(std::is_same_v<std::coroutine_traits<__VA_ARGS__>::promise_type, promise>);
6575
using namespace dd;
@@ -1093,7 +1103,9 @@ TEST(expected_e) {
10931103
} \
10941104
}
10951105

1096-
#define CHECK_ALIGN(sz, pad, expected) static_assert(::dd::noexport::padding_len<pad>(sz) == expected);
1106+
#define CHECK_ALIGN(sz, align, expected_padding) \
1107+
static_assert(::dd::noexport::padding_len<align>(sz) == expected_padding); \
1108+
static_assert(::dd::noexport::aligned<align>(sz) == (sz + expected_padding));
10971109

10981110
CHECK_ALIGN(0, 8, 0);
10991111
CHECK_ALIGN(16, 16, 0);

0 commit comments

Comments
 (0)