Getting ready to shift to dlmalloc
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "drivertests.hpp"
|
||||
#include "drivenengine.hpp"
|
||||
#include "world.hpp"
|
||||
#include "eng-malloc.hpp"
|
||||
#include <iomanip>
|
||||
|
||||
static void write_closed_message(Channel *ch, StreamBuffer *out) {
|
||||
@@ -92,7 +93,7 @@ public:
|
||||
virtual void event_update() {
|
||||
double clock = get_clock();
|
||||
if (clock > last_clock_ + 0.5) {
|
||||
int ms = util::hash_of_mallocs();
|
||||
int ms = dlmalloc_hash();
|
||||
stdostream() << std::fixed << std::setprecision(2) << clock << " " << std::hex << ms << " ";
|
||||
count_++;
|
||||
last_clock_ = clock;
|
||||
|
||||
64
luprex/core/cpp/eng-malloc.cpp
Normal file
64
luprex/core/cpp/eng-malloc.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// We only use a custom allocator on linux (for now)
|
||||
// The allocator we chose is 'dlmalloc' (doug lea's malloc).
|
||||
// It's a good allocator for single-threaded programs.
|
||||
// It needs to be configured by setting a bunch of defines.
|
||||
//
|
||||
#ifdef __linux__
|
||||
|
||||
// We need this to define dlmalloc, not malloc.
|
||||
#define USE_DL_PREFIX 1
|
||||
|
||||
// We don't need mspaces.
|
||||
#define ONLY_MSPACES 0
|
||||
#define MSPACES 0
|
||||
|
||||
// We don't need mallinfo
|
||||
#define NO_MALLINFO 1
|
||||
|
||||
// We don't need dlmalloc_inspect_all
|
||||
#define MALLOC_INSPECT_ALL 0
|
||||
|
||||
// We don't need dlmalloc_stats.
|
||||
#define NO_MALLOC_STATS 1
|
||||
|
||||
// Disable locking. The entire engine is single-threaded.
|
||||
#define USE_LOCKS 0
|
||||
|
||||
// For now, we'll let the allocator use mmap to get memory.
|
||||
// It's not clear if this is going to be deterministic.
|
||||
#define HAVE_MMAP 1
|
||||
|
||||
// One way to force determinism would be to emulate sbrk
|
||||
// using mmap and mremap, always putting the heap at a fixed
|
||||
// address. For now, we're not doing that, we're just
|
||||
// using mmap and relying on that being deterministic (we hope).
|
||||
#define HAVE_MORECORE 0
|
||||
#define MORECORE emulate_sbrk
|
||||
|
||||
// The properties of mmap under linux
|
||||
#define MMAP_CLEARS 1
|
||||
#define HAVE_MREMAP 1
|
||||
|
||||
// Don't generate random seeds, or time-based seeds.
|
||||
#define USE_DEV_RANDOM 0
|
||||
#define LACKS_TIME_H 1
|
||||
|
||||
#include "dlmalloc/dlmalloc.c"
|
||||
|
||||
#endif
|
||||
|
||||
int dlmalloc_hash() {
|
||||
void *blocks[15];
|
||||
int hash = 0;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
void *blk = dlmalloc(1 << i);
|
||||
blocks[i] = blk;
|
||||
hash = (hash * 17) + (int)(intptr_t)(blk);
|
||||
}
|
||||
for (int i = 0; i < 15; i++) {
|
||||
free(blocks[i]);
|
||||
}
|
||||
return (hash & 0x7FFFFFFF) | (0x40000000);
|
||||
}
|
||||
|
||||
105
luprex/core/cpp/eng-malloc.hpp
Normal file
105
luprex/core/cpp/eng-malloc.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
|
||||
|
||||
#ifndef ENG_MALLOC_HPP
|
||||
#define ENG_MALLOC_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <sstream>
|
||||
|
||||
// dlmalloc is only used on linux.
|
||||
extern "C" {
|
||||
#ifdef __linux__
|
||||
void* dlmalloc(size_t x);
|
||||
void dlfree(void *p);
|
||||
void* dlrealloc(void*, size_t);
|
||||
#else
|
||||
void* dlmalloc(size_t x) { return malloc(x); }
|
||||
void dlfree(void *p) { free(p); }
|
||||
void* dlrealloc(void *p, size_t x) { return realloc(p,x); }
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return the current state of the dlmalloc allocator as a 30-bit hash.
|
||||
extern int dlmalloc_hash();
|
||||
|
||||
// EngAllocator: a class meant to be used as an STL Allocator.
|
||||
// Causes objects to be allocated using dlmalloc and dlfree.
|
||||
template <class T>
|
||||
class EngAllocator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
EngAllocator() noexcept {}
|
||||
template <class U> EngAllocator(EngAllocator<U> const&) noexcept {}
|
||||
|
||||
value_type* allocate(std::size_t n)
|
||||
{
|
||||
return static_cast<value_type*>(dlmalloc(n*sizeof(value_type)));
|
||||
}
|
||||
|
||||
void deallocate(value_type* p, std::size_t) noexcept
|
||||
{
|
||||
dlfree(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
bool operator==(EngAllocator<T> const&, EngAllocator<U> const&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool operator!=(EngAllocator<T> const&, EngAllocator<U> const&) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace eng {
|
||||
|
||||
template<class T>
|
||||
using hash = std::hash<T>;
|
||||
|
||||
template<class T>
|
||||
using less = std::less<T>;
|
||||
|
||||
template<class T>
|
||||
using equal_to = std::equal_to<T>;
|
||||
|
||||
template<class T>
|
||||
using char_traits = std::char_traits<T>;
|
||||
|
||||
template<class A, class B>
|
||||
using pair = std::pair<A, B>;
|
||||
|
||||
template<class C, class T=char_traits<C>>
|
||||
using basic_string = std::basic_string<C, T, EngAllocator<C>>;
|
||||
|
||||
template<class C, class T=char_traits<C>>
|
||||
using basic_stringstream = std::basic_stringstream<C, T, EngAllocator<C>>;
|
||||
|
||||
template<class T>
|
||||
using vector = std::vector<T, EngAllocator<T>>;
|
||||
|
||||
template<class K, class V, class C=less<K>>
|
||||
using map = std::map<K, V, C, EngAllocator<pair<const K, V>>>;
|
||||
|
||||
template<class K, class V, class H=hash<K>, class E=equal_to<K>>
|
||||
using unordered_map = std::unordered_map<K, V, H, E, EngAllocator<pair<const K, V>>>;
|
||||
|
||||
template<class K, class C=std::less<K>>
|
||||
using set = std::set<K, C, EngAllocator<K>>;
|
||||
|
||||
template<class K, class H=hash<K>, class E=equal_to<K>>
|
||||
using unordered_set = std::unordered_set<K, H, E, EngAllocator<K>>;
|
||||
|
||||
using string = basic_string<char>;
|
||||
using stringstream = basic_stringstream<char>;
|
||||
}
|
||||
#endif // ENG_MALLOC_HPP
|
||||
|
||||
@@ -353,20 +353,6 @@ bool is_lua_comment(const std::string &s) {
|
||||
return s.substr(start, 2) == "--";
|
||||
}
|
||||
|
||||
int hash_of_mallocs() {
|
||||
void *blocks[15];
|
||||
int hash = 0;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
void *blk = malloc(1 << i);
|
||||
blocks[i] = blk;
|
||||
hash = (hash * 17) + (int)(ptrdiff_t)(blk);
|
||||
}
|
||||
for (int i = 0; i < 15; i++) {
|
||||
free(blocks[i]);
|
||||
}
|
||||
return (hash & 0x7FFFFFFF) | (0x40000000);
|
||||
}
|
||||
|
||||
std::string XYZ::debug_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << "(" << x << "," << y << "," << z << ")";
|
||||
|
||||
@@ -125,11 +125,6 @@ LuaSourcePtr make_lua_source(const std::string &code);
|
||||
// Return true if the line of code is a lua comment.
|
||||
bool is_lua_comment(const std::string &line);
|
||||
|
||||
// Malloc some blocks of RAM, and calculate a hash from
|
||||
// their addresses. This can be used to determine if the malloc
|
||||
// heap is in a deterministic state.
|
||||
int hash_of_mallocs();
|
||||
|
||||
// Remove nullptrs from a vector of unique pointers.
|
||||
template<class T>
|
||||
void remove_nullptrs(std::vector<std::unique_ptr<T>> &vec) {
|
||||
|
||||
Reference in New Issue
Block a user