-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2900 from rnlahaye/magic_alloc
Use system allocator for containers on macOS (bypassing Unity's allocator)
- Loading branch information
Showing
7 changed files
with
214 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// This file contains aliases of some STL containers (such as `std::vector`) in | ||
// the `principia::std` namespace with their default allocators overridden to | ||
// base new one defined here. The result of this is that if you write | ||
// `std::vector foo` inside the principia namespace, it will resolve to a vector | ||
// with the allocator defined here. | ||
// | ||
// The intended purpose of this file is to be used on macOS builds. This is | ||
// necessary because Unity provides overrides of `new` and `delete` which have | ||
// terrible performance on macOS. It should be included via compiler argument. | ||
// Attempting to include it on non-macOS builds will result in an error. | ||
|
||
#pragma once | ||
|
||
#include <deque> | ||
#include <list> | ||
#include <map> | ||
#include <set> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "base/macros.hpp" | ||
#include "base/malloc_allocator.hpp" | ||
|
||
#if !OS_MACOSX | ||
#error Only include this file for macOS | ||
#endif | ||
|
||
namespace principia { | ||
namespace std { | ||
|
||
using namespace ::std; | ||
|
||
template<typename T> | ||
using allocator = ::principia::base::MallocAllocator<T>; | ||
|
||
template<typename T, typename Allocator = allocator<T>> | ||
using vector = ::std::vector<T, Allocator>; | ||
|
||
template<typename T, typename Allocator = allocator<T>> | ||
using deque = ::std::deque<T, Allocator>; | ||
|
||
template<typename T, typename Allocator = allocator<T>> | ||
using list = ::std::list<T, Allocator>; | ||
|
||
template<typename Key, | ||
typename Compare = std::less<Key>, | ||
typename Allocator = allocator<Key>> | ||
using set = ::std::set<Key, Compare, Allocator>; | ||
|
||
template<typename Key, | ||
typename T, | ||
typename Compare = std::less<Key>, | ||
typename Allocator = allocator<std::pair<const Key, T>>> | ||
using map = ::std::map<Key, T, Compare, Allocator>; | ||
|
||
template<typename Key, | ||
typename Compare = std::less<Key>, | ||
typename Allocator = allocator<Key>> | ||
using multiset = ::std::multiset<Key, Compare, Allocator>; | ||
|
||
template<typename Key, | ||
typename T, | ||
typename Compare = std::less<Key>, | ||
typename Allocator = allocator<std::pair<const Key, T>>> | ||
using multimap = ::std::multimap<Key, T, Compare, Allocator>; | ||
|
||
} // namespace std | ||
} // namespace principia |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
|
||
// "macos_allocator_replacement.hpp" should be automagically included. | ||
|
||
#include <deque> | ||
#include <list> | ||
#include <map> | ||
#include <set> | ||
#include <type_traits> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "base/macros.hpp" | ||
#include "base/malloc_allocator.hpp" | ||
#include "gmock/gmock.h" | ||
#include "gtest/gtest.h" | ||
|
||
#ifdef OS_MACOSX | ||
|
||
namespace principia { | ||
namespace magic { | ||
|
||
using base::MallocAllocator; | ||
|
||
// AllocatorIs<container, alloc>() returns true iff container's allocator is | ||
// alloc. | ||
template<typename T, typename Allocator> | ||
constexpr bool AllocatorIs() { | ||
return std::is_same<typename T::allocator_type, Allocator>::value; | ||
} | ||
|
||
// Test that the default allocators for various classes are overridden. | ||
TEST(PrincipiaMallocAllocatorTest, DefaultAllocators) { | ||
// STL | ||
EXPECT_TRUE((AllocatorIs<std::vector<int>, MallocAllocator<int>>())); | ||
EXPECT_TRUE((AllocatorIs<std::deque<int>, MallocAllocator<int>>())); | ||
EXPECT_TRUE((AllocatorIs<std::list<int>, MallocAllocator<int>>())); | ||
EXPECT_TRUE((AllocatorIs<std::set<int>, MallocAllocator<int>>())); | ||
EXPECT_TRUE((AllocatorIs<std::map<int, int>, | ||
MallocAllocator<std::pair<const int, int>>>())); | ||
EXPECT_TRUE((AllocatorIs<std::multiset<int>, MallocAllocator<int>>())); | ||
EXPECT_TRUE((AllocatorIs<std::multimap<int, int>, | ||
MallocAllocator<std::pair<const int, int>>>())); | ||
} | ||
|
||
} // namespace magic | ||
} // namespace principia | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
|
||
#pragma once | ||
|
||
#include <cstddef> | ||
#include <cstdlib> | ||
|
||
namespace principia { | ||
namespace base { | ||
|
||
// An allocator (for use with containers such as `std::vector`) that uses malloc | ||
// and free for memory management instead of global new and delete. The purpose | ||
// of this allocator is to enable use of the system allocator even when global | ||
// new and delete have been overridden. | ||
template<typename T> | ||
class MallocAllocator { | ||
public: | ||
using value_type = T; | ||
using pointer = T*; | ||
using const_pointer = T const*; | ||
using reference = T&; | ||
using const_reference = T const&; | ||
using size_type = std::size_t; | ||
using difference_type = std::ptrdiff_t; | ||
|
||
T* allocate(size_t n) { | ||
return static_cast<T*>(calloc(n, sizeof(T))); | ||
} | ||
|
||
void deallocate(T* p, size_t n) { | ||
free(p); | ||
} | ||
}; | ||
|
||
// MallocAllocators are equal regardless of type. | ||
template<typename T1, typename T2> | ||
constexpr bool operator==(const MallocAllocator<T1>&, | ||
const MallocAllocator<T2>&) { | ||
return true; | ||
} | ||
|
||
template<typename T1, typename T2> | ||
constexpr bool operator!=(const MallocAllocator<T1>&, | ||
const MallocAllocator<T2>&) { | ||
return false; | ||
} | ||
|
||
} // namespace base | ||
} // namespace principia |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
|
||
#include "base/malloc_allocator.hpp" | ||
|
||
#include <cstdlib> | ||
|
||
#include "gmock/gmock.h" | ||
#include "gtest/gtest.h" | ||
|
||
namespace principia { | ||
namespace base { | ||
|
||
using ::testing::IsNull; | ||
using ::testing::Not; | ||
|
||
TEST(MallocAllocatorTest, Allocate) { | ||
int* p; | ||
p = MallocAllocator<int>().allocate(1); | ||
EXPECT_THAT(p, Not(IsNull())); | ||
*p = 123; | ||
free(p); | ||
|
||
p = MallocAllocator<int>().allocate(10); | ||
EXPECT_THAT(p, Not(IsNull())); | ||
p[9] = 123; | ||
free(p); | ||
} | ||
|
||
TEST(MallocAllocatorTest, Deallocate) { | ||
int* p = static_cast<int*>(malloc(sizeof(int))); | ||
MallocAllocator<int>().deallocate(p, 1); | ||
} | ||
|
||
TEST(MallocAllocatorTest, RoundTrip) { | ||
int* p; | ||
p = MallocAllocator<int>().allocate(1); | ||
EXPECT_THAT(p, Not(IsNull())); | ||
*p = 123; | ||
MallocAllocator<int>().deallocate(p, 1); | ||
} | ||
|
||
} // namespace base | ||
} // namespace principia |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters