OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ArenaAllocator.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include "DataMgr/DataMgr.h"
20 #include "Shared/checked_alloc.h"
21 
22 template <class T>
23 class SysAllocator {
24  public:
25  using Self = SysAllocator;
26  using value_type = T;
27 
28  constexpr SysAllocator() = default;
29 
30  constexpr SysAllocator(SysAllocator const&) = default;
31 
32  template <class U>
33  constexpr SysAllocator(const SysAllocator<U>&) noexcept {}
34 
35  [[nodiscard]] T* allocate(size_t count) {
36  return reinterpret_cast<T*>(checked_malloc(count));
37  }
38 
39  void deallocate(T* p, size_t /* count */) { free(p); }
40 
41  friend bool operator==(Self const&, Self const&) noexcept { return true; }
42  friend bool operator!=(Self const&, Self const&) noexcept { return false; }
43 };
44 
45 class Arena {
46  public:
47  enum class MemoryType { DRAM, PMEM };
48  virtual ~Arena() {}
49  virtual void* allocate(size_t size) = 0;
50  virtual void* allocateAndZero(const size_t size) = 0;
51  virtual size_t bytesUsed() const = 0;
52  virtual size_t totalBytes() const = 0;
53  virtual MemoryType getMemoryType() const = 0;
54 };
55 
56 #ifdef HAVE_FOLLY
57 
58 #include <folly/Memory.h>
59 #include <folly/memory/Arena.h>
60 
61 using AllocatorType = char;
62 
63 constexpr size_t kArenaBlockOverhead =
64  folly::Arena<::SysAllocator<AllocatorType>>::kBlockOverhead;
65 
70 class DramArena : public Arena, public folly::Arena<::SysAllocator<AllocatorType>> {
71  public:
72  explicit DramArena(size_t min_block_size = static_cast<size_t>(1ULL << 32) +
73  kBlockOverhead,
74  size_t size_limit = kNoSizeLimit,
75  size_t max_align = kDefaultMaxAlign)
76  : folly::Arena<::SysAllocator<AllocatorType>>({},
77  min_block_size,
78  size_limit,
79  max_align) {}
80  ~DramArena() override {}
81 
82  void* allocate(size_t size) override {
83  return folly::Arena<::SysAllocator<AllocatorType>>::allocate(size);
84  }
85 
86  void* allocateAndZero(const size_t size) override {
87  auto ret = allocate(size);
88  std::memset(ret, 0, size);
89  return ret;
90  }
91 
92  size_t bytesUsed() const override {
93  return folly::Arena<::SysAllocator<AllocatorType>>::bytesUsed();
94  }
95 
96  size_t totalBytes() const override {
97  return folly::Arena<::SysAllocator<AllocatorType>>::totalSize();
98  }
99 
100  MemoryType getMemoryType() const override { return MemoryType::DRAM; }
101 };
102 
103 template <>
104 struct folly::ArenaAllocatorTraits<::SysAllocator<AllocatorType>> {
105  static size_t goodSize(const ::SysAllocator<AllocatorType>& /* alloc */, size_t size) {
106  return folly::goodMallocSize(size);
107  }
108 };
109 
110 #else
111 
112 constexpr size_t kArenaBlockOverhead = 0;
113 
119 class DramArena : public Arena {
120  public:
121  explicit DramArena(size_t min_block_size = 1ULL << 32, size_t size_limit = 0)
122  : size_limit_(size_limit), size_(0) {}
123 
124  ~DramArena() override {
125  for (auto [ptr, size] : allocations_) {
126  allocator_.deallocate(ptr, 0);
127  size_ -= size;
128  }
129  }
130 
131  void* allocate(size_t num_bytes) override {
132  if (size_limit_ != 0 && size_ + num_bytes > size_limit_) {
133  throw OutOfHostMemory(num_bytes);
134  }
135  auto ret = allocator_.allocate(num_bytes);
136  size_ += num_bytes;
137  allocations_.push_back({ret, num_bytes});
138  return ret;
139  }
140 
141  void* allocateAndZero(const size_t size) override {
142  auto ret = allocate(size);
143  std::memset(ret, 0, size);
144  return ret;
145  }
146 
147  size_t bytesUsed() const override { return size_; }
148 
149  size_t totalBytes() const override { return size_; }
150 
151  MemoryType getMemoryType() const override { return MemoryType::DRAM; }
152 
153  private:
154  size_t size_limit_;
155  size_t size_;
157  std::vector<std::pair<void*, size_t>> allocations_;
158 };
159 
160 #endif
constexpr size_t kArenaBlockOverhead
void * allocate(size_t num_bytes) override
virtual MemoryType getMemoryType() const =0
friend bool operator!=(Self const &, Self const &) noexcept
virtual size_t totalBytes() const =0
constexpr SysAllocator()=default
T * allocate(size_t count)
virtual size_t bytesUsed() const =0
void deallocate(T *p, size_t)
size_t size_
virtual void * allocate(size_t size)=0
size_t size_limit_
size_t bytesUsed() const override
void * checked_malloc(const size_t size)
Definition: checked_alloc.h:45
size_t totalBytes() const override
SysAllocator< void > allocator_
constexpr SysAllocator(const SysAllocator< U > &) noexcept
DramArena(size_t min_block_size=1ULL<< 32, size_t size_limit=0)
virtual ~Arena()
void * allocateAndZero(const size_t size) override
~DramArena() override
friend bool operator==(Self const &, Self const &) noexcept
MemoryType getMemoryType() const override
std::vector< std::pair< void *, size_t > > allocations_
virtual void * allocateAndZero(const size_t size)=0