Skip to content

Commit

Permalink
huge paging
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilipDeegan committed Oct 8, 2024
1 parent 0a112d5 commit 48948bd
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 32 deletions.
86 changes: 82 additions & 4 deletions inc/mkn/kul/alloc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib>
#include <type_traits>

#include <limits>
#include <stdlib.h> // posix_memalign
#include <sys/mman.h> // madvise

namespace mkn::kul {

template <typename T, std::int32_t alignment = 32>
Expand Down Expand Up @@ -98,10 +102,7 @@ class Allocator {
using other = Allocator<U>;
};

T* allocate(std::size_t const n) const {
if (n == 0) return nullptr;
return static_cast<T*>(::operator new(n * sizeof(T)));
}
T* allocate(std::size_t const n) const { return static_cast<T*>(::operator new(n * sizeof(T))); }

void deallocate(T* const p) noexcept {
if (p) ::operator delete(p);
Expand All @@ -117,16 +118,93 @@ class Allocator {

template <typename T>
class NonConstructingAllocator : public Allocator<T> {
using This = NonConstructingAllocator<T>;

public:
template <typename U>
struct rebind {
using other = NonConstructingAllocator<U>;
};

T* allocate(std::size_t const n) const {
// if (n == 0) return nullptr;
return static_cast<T*>(malloc(n * sizeof(T)));
}

template <typename U, typename... Args>
void construct(U* /*ptr*/, Args&&... /*args*/) {} // nothing
template <typename U>
void construct(U* /*ptr*/) noexcept(std::is_nothrow_default_constructible<U>::value) {}

bool operator!=(This const& that) const { return !(*this == that); }
bool operator==(This const& /*that*/) const {
return true; // stateless
}
};

template <typename T, std::size_t huge_page_size = 4096>
class HugePageAllocator : public Allocator<T> {
using This = HugePageAllocator<T, huge_page_size>;

public:
template <typename U>
struct rebind {
using other = HugePageAllocator<U>;
};

HugePageAllocator() = default;
template <class U>
constexpr HugePageAllocator(HugePageAllocator<U> const&) noexcept {}

T* allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) throw std::bad_alloc();
void* p = nullptr;
posix_memalign(&p, huge_page_size, n * sizeof(T));
madvise(p, n * sizeof(T), MADV_HUGEPAGE);
if (p == nullptr) throw std::bad_alloc();
return static_cast<T*>(p);
}
void deallocate(T* p, std::size_t n) { std::free(p); }
bool operator!=(This const& that) const { return !(*this == that); }
bool operator==(This const& /*that*/) const {
return true; // stateless
}
};

template <typename T, std::size_t huge_page_size = 4096>
class NonConstructingHugePageAllocator : public NonConstructingAllocator<T> {
using This = NonConstructingHugePageAllocator<T, huge_page_size>;

public:
template <typename U>
struct rebind {
using other = NonConstructingHugePageAllocator<U>;
};

NonConstructingHugePageAllocator() = default;
template <class U>
constexpr NonConstructingHugePageAllocator(NonConstructingHugePageAllocator<U> const&) noexcept {}

T* allocate(std::size_t n) {
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) throw std::bad_alloc();
void* p = nullptr;
posix_memalign(&p, huge_page_size, n * sizeof(T));
madvise(p, n * sizeof(T), MADV_HUGEPAGE);
if (p == nullptr) throw std::bad_alloc();
return static_cast<T*>(p);
}

void deallocate(T* p, std::size_t n) { std::free(p); }

template <typename U, typename... Args>
void construct(U* /*ptr*/, Args&&... /*args*/) {} // nothing
template <typename U>
void construct(U* /*ptr*/) noexcept(std::is_nothrow_default_constructible<U>::value) {}

bool operator!=(This const& that) const { return !(*this == that); }
bool operator==(This const& /*that*/) const {
return true; // stateless
}
};

} // namespace mkn::kul
Expand Down
30 changes: 21 additions & 9 deletions inc/mkn/kul/vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _MKN_KUL_VECTOR_HPP_
#define _MKN_KUL_VECTOR_HPP_

#include "alloc.hpp"
#include "mkn/kul/alloc.hpp"

#include <vector>
#include <type_traits>

namespace mkn::kul {

template <typename T, typename A = void> // A ignored but there for std::vector interop
template <typename T> // A ignored but there for std::vector interop
using Vector = std::vector<T, Allocator<T>>;

template <typename T> // A ignored but there for std::vector interop
using NonConstructingVector = std::vector<T, NonConstructingAllocator<T>>;

template <typename T, std::size_t S = 4096>
using NonConstructingHugePageVector = std::vector<T, NonConstructingHugePageAllocator<T, S>>;

template <typename T, std::size_t S = 4096>
using HugePageVector = std::vector<T, HugePageAllocator<T, S>>;

template <typename T>
std::vector<T, Allocator<T>>& as_super(std::vector<T, NonConstructingAllocator<T>>& v) {
return *reinterpret_cast<std::vector<T, Allocator<T>>*>(&v);
Expand All @@ -51,26 +62,27 @@ std::vector<T, Allocator<T>> const& as_super(std::vector<T, NonConstructingAlloc

} // namespace mkn::kul

template <typename T, typename A0, typename A1 = void>
bool operator==(std::vector<T, A0> const& v0, mkn::kul::NonConstructingVector<T, A1> const& v1) {
template <typename T, typename A0, typename A1,
std::enable_if_t<std::is_base_of_v<mkn::kul::Allocator<T>, A1>, bool> = 0>
bool operator==(std::vector<T, A0> const& v0, std::vector<T, A1> const& v1) {
if (v0.size() != v1.size()) return false;
for (std::size_t i = 0; i < v0.size(); i++)
if (v0[i] != v1[i]) return false;
return true;
}

template <typename T, typename A0, typename A1 = void>
bool operator==(mkn::kul::NonConstructingVector<T, A1> const& v0, std::vector<T, A0> const& v1) {
template <typename T, typename A0>
bool operator==(mkn::kul::Vector<T> const& v0, std::vector<T, A0> const& v1) {
return v1 == v0;
}

template <typename T, typename A0, typename A1 = void>
bool operator!=(std::vector<T, A0> const& v0, mkn::kul::NonConstructingVector<T, A1> const& v1) {
template <typename T, typename A0>
bool operator!=(std::vector<T, A0> const& v0, mkn::kul::Vector<T> const& v1) {
return !(v0 == v1);
}

template <typename T, typename A0, typename A1 = void>
bool operator!=(mkn::kul::NonConstructingVector<T, A1> const& v0, std::vector<T, A0> const& v1) {
template <typename T, typename A0>
bool operator!=(mkn::kul::Vector<T> const& v0, std::vector<T, A0> const& v1) {
return !(v0 == v1);
}

Expand Down
13 changes: 9 additions & 4 deletions mkn.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! clean build -dtOp test
#! clean build -dtKOp test

# mkn.kul - Kommon Usage Library
# Cross platform wrapper for systems operations / IO / threads / processes
Expand Down Expand Up @@ -28,16 +28,21 @@ profile:
nix: ./src/os/nixish
arg: -D_MKN_KUL_COMPILED_LIB_

- name: test

- name: _test
parent: lib
inc: .
main: test/test.cpp
src: test/test
mode: none
dep: google.test
if_arg:
win_shared: -DGTEST_LINKED_AS_SHARED_LIBRARY=1

- name: test
parent: _test
main: test/test.cpp
src: test/test
mode: none

- name: bench
parent: lib
main: test/bench.cpp
Expand Down
67 changes: 52 additions & 15 deletions test/test/no_construct_alloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <array>
#include <cstddef>
#include <cstring>
#include <algorithm>
#include <stdexcept>

Expand Down Expand Up @@ -61,6 +62,27 @@ auto copy_manual(V const& v) {
return out;
}

template <typename V>
auto copy_mem(V const& v) {
KUL_DBG_FUNC_ENTER;
V out;
out.reserve(v.capacity());
out.resize(v.size());
memcpy(out.data(), v.data(), v.size() * sizeof(typename V::value_type));
return out;
}

template <typename V>
auto copy_loop(V const& v) {
KUL_DBG_FUNC_ENTER;
V out;
out.reserve(v.capacity());
out.resize(v.size());
for (std::size_t i = 0; i < v.size(); ++i) out[i] = v[i];
// memcpy(out.data(), v.data(), v.size() * sizeof(typename V::value_type));
return out;
}

template <typename V>
auto make_vector(std::size_t const& size) {
KUL_DBG_FUNC_ENTER;
Expand All @@ -74,25 +96,40 @@ auto make_vector_from(V1 const& v1) {
return v;
}

template <typename V0>
void resize(V0& v) {
KUL_DBG_FUNC_ENTER;
v.resize(v.capacity() + 1); // force reallocation
}

template <typename T>
void do_compare() {
constexpr static std::size_t N = 2000000;
auto const std_vec = make_vector<std::vector<T>>(N);
auto const std_vec2 = make_vector_from<std::vector<T>>(std_vec);
auto const no_construct_vec = make_vector_from<mkn::kul::NonConstructingVector<T>>(std_vec);
if (std_vec != no_construct_vec) throw std::runtime_error("FAIL");
if (std_vec != std_vec2) throw std::runtime_error("FAIL");
auto const v0 = copy_construct(std_vec);
auto const v1 = copy_construct(no_construct_vec);
auto const v2 = copy_manual(std_vec);
auto const v3 = copy_manual(no_construct_vec);
auto const v4 = copy_operator_equal_super(no_construct_vec);

if (v0 != std_vec) throw std::runtime_error("FAIL 0");
if (v0 == v1) throw std::runtime_error("FAIL 1"); // :(
if (v0 != v2) throw std::runtime_error("FAIL 2");
if (v0 != v3) throw std::runtime_error("FAIL 3");
if (v0 != v4) throw std::runtime_error("FAIL 4");

auto wash = [&]<typename V>(auto const& name) {
KOUT(NON) << name;
auto const copy = make_vector_from<V>(v0);
auto const v1 = copy_mem(copy);
auto const v2 = copy_loop(copy);
auto const v3 = copy_manual(copy);

if (v0 != v1) throw std::runtime_error("FAIL 1"); // :(
if (v0 != v2) throw std::runtime_error("FAIL 2");
if (v0 != v3) throw std::runtime_error("FAIL 3");
};

using namespace mkn::kul;
wash.template operator()<std::vector<T>>("std::vector<T>");
wash.template operator()<NonConstructingVector<T>>("NonConstructingVector<T>");
wash.template operator()<HugePageVector<T>>("HugePageVector<T>");
wash.template operator()<NonConstructingHugePageVector<T>>("NonConstructingHugePageVector<T>");
}

TEST(NoConstructAllocator, copies) { do_compare<S<8>>(); }
TEST(NoConstructAllocator, copies) { do_compare<double>(); }

// int main(int argc, char* argv[]) {
// ::testing::InitGoogleTest(&argc, argv);
// return RUN_ALL_TESTS();
// }

0 comments on commit 48948bd

Please sign in to comment.