Add initial memory domain allocation tracking support

This commit is contained in:
Maxime Coste 2015-01-07 19:29:31 +00:00
parent de12fe1cc6
commit 9b30e7469a
8 changed files with 120 additions and 15 deletions

View File

@ -801,7 +801,7 @@ const CommandDesc debug_cmd = {
PerArgumentCommandCompleter({
[](const Context& context, CompletionFlags flags,
const String& prefix, ByteCount cursor_pos) -> Completions {
auto c = {"info", "buffers", "options"};
auto c = {"info", "buffers", "options", "memory"};
return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) };
} }),
[](const ParametersParser& parser, Context& context)
@ -823,6 +823,16 @@ const CommandDesc debug_cmd = {
for (auto& option : context.options().flatten_options())
write_debug(" * " + option->name() + ": " + option->get_as_string());
}
else if (parser[0] == "memory")
{
write_debug("Memory usage:");
write_debug("String: " + to_string(UsedMemory<MemoryDomain::String>::byte_count));
write_debug("InternedString: " + to_string(UsedMemory<MemoryDomain::InternedString>::byte_count));
write_debug("BufferContent: " + to_string(UsedMemory<MemoryDomain::BufferContent>::byte_count));
write_debug("BufferMeta: " + to_string(UsedMemory<MemoryDomain::BufferMeta>::byte_count));
write_debug("WordDB: " + to_string(UsedMemory<MemoryDomain::WordDB>::byte_count));
write_debug("Undefined: " + to_string(UsedMemory<MemoryDomain::Undefined>::byte_count));
}
else
throw runtime_error("unknown debug command '" + parser[0] + "'");
}

View File

@ -3,18 +3,17 @@
#include "containers.hh"
#include "string.hh"
#include <vector>
#include "vector.hh"
namespace Kakoune
{
template<typename Value>
template<typename Value, MemoryDomain domain = MemoryDomain::Undefined>
class IdMap
{
public:
using value_type = std::pair<String, Value>;
using container_type = std::vector<value_type>;
using container_type = Vector<value_type, domain>;
using iterator = typename container_type::iterator;
using const_iterator = typename container_type::const_iterator;

View File

@ -47,11 +47,11 @@ void StringRegistry::release(size_t slot) noexcept
if (--m_storage[slot].refcount == 0)
{
m_free_slots.push_back(slot);
std::vector<char>& data = m_storage[slot].data;
auto& data = m_storage[slot].data;
auto it = m_slot_map.find(StringView{data.data(), (int)data.size()});
kak_assert(it != m_slot_map.end());
m_slot_map.erase(it);
data = std::vector<char>{};
data = Vector<char, MemoryDomain::InternedString>{};
}
}

View File

@ -4,6 +4,7 @@
#include "string.hh"
#include "utils.hh"
#include "unordered_map.hh"
#include "vector.hh"
namespace Kakoune
{
@ -20,9 +21,13 @@ private:
void release(size_t slot) noexcept;
UnorderedMap<StringView, size_t> m_slot_map;
std::vector<size_t> m_free_slots;
struct DataAndRefCount { std::vector<char> data; int refcount; };
std::vector<DataAndRefCount> m_storage;
Vector<size_t, MemoryDomain::InternedString> m_free_slots;
struct DataAndRefCount
{
Vector<char, MemoryDomain::InternedString> data;
int refcount;
};
Vector<DataAndRefCount, MemoryDomain::InternedString> m_storage;
};
class InternedString : public StringView

72
src/memory.hh Normal file
View File

@ -0,0 +1,72 @@
#ifndef memory_hh_INCLUDED
#define memory_hh_INCLUDED
#include <cstdlib>
#include "assert.hh"
namespace Kakoune
{
enum class MemoryDomain
{
Undefined,
String,
InternedString,
BufferContent,
BufferMeta,
WordDB
};
template<MemoryDomain domain>
struct UsedMemory
{
static size_t byte_count;
};
template<MemoryDomain domain>
size_t UsedMemory<domain>::byte_count = 0;
template<typename T, MemoryDomain domain>
struct Allocator
{
using value_type = T;
Allocator() = default;
template<typename U>
Allocator(const Allocator<U, domain>&) {}
template<typename U>
struct rebind { using other = Allocator<U, domain>; };
T* allocate(size_t n)
{
size_t size = sizeof(T) * n;
UsedMemory<domain>::byte_count += size;
return reinterpret_cast<T*>(malloc(size));
}
void deallocate(T* ptr, size_t n)
{
size_t size = sizeof(T) * n;
kak_assert(UsedMemory<domain>::byte_count >= size);
UsedMemory<domain>::byte_count -= size;
free(ptr);
}
};
template<typename T1, MemoryDomain d1, typename T2, MemoryDomain d2>
bool operator==(const Allocator<T1, d1>& lhs, const Allocator<T2, d2>& rhs)
{
return d1 == d2;
}
template<typename T1, MemoryDomain d1, typename T2, MemoryDomain d2>
bool operator!=(const Allocator<T1, d1>& lhs, const Allocator<T2, d2>& rhs)
{
return d1 != d2;
}
}
#endif // memory_hh_INCLUDED

View File

@ -2,14 +2,16 @@
#define unordered_map_hh_INCLUDED
#include "hash.hh"
#include "memory.hh"
#include <unordered_map>
namespace Kakoune
{
template<typename Key, typename Value>
using UnorderedMap = std::unordered_map<Key, Value, Hash<Key>>;
template<typename Key, typename Value, MemoryDomain domain = MemoryDomain::Undefined>
using UnorderedMap = std::unordered_map<Key, Value, Hash<Key>, std::equal_to<Key>,
Allocator<std::pair<const Key, Value>, domain>>;
}

16
src/vector.hh Normal file
View File

@ -0,0 +1,16 @@
#ifndef vector_hh_INCLUDED
#define vector_hh_INCLUDED
#include "memory.hh"
#include <vector>
namespace Kakoune
{
template<typename T, MemoryDomain domain = MemoryDomain::Undefined>
using Vector = std::vector<T, Allocator<T, domain>>;
}
#endif // vector_hh_INCLUDED

View File

@ -3,8 +3,9 @@
#include "buffer.hh"
#include "interned_string.hh"
#include "unordered_map.hh"
#include "vector.hh"
#include <map>
#include <bitset>
namespace Kakoune
@ -44,9 +45,9 @@ public:
UsedLetters letters;
int refcount;
};
using WordToInfo = UnorderedMap<InternedString, WordInfo>;
using WordToInfo = UnorderedMap<InternedString, WordInfo, MemoryDomain::WordDB>;
private:
using LineToWords = std::vector<WordList>;
using LineToWords = Vector<WordList, MemoryDomain::WordDB>;
void update_db();
void add_words(const WordList& words);