Add initial memory domain allocation tracking support
This commit is contained in:
parent
de12fe1cc6
commit
9b30e7469a
|
@ -801,7 +801,7 @@ const CommandDesc debug_cmd = {
|
||||||
PerArgumentCommandCompleter({
|
PerArgumentCommandCompleter({
|
||||||
[](const Context& context, CompletionFlags flags,
|
[](const Context& context, CompletionFlags flags,
|
||||||
const String& prefix, ByteCount cursor_pos) -> Completions {
|
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) };
|
return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) };
|
||||||
} }),
|
} }),
|
||||||
[](const ParametersParser& parser, Context& context)
|
[](const ParametersParser& parser, Context& context)
|
||||||
|
@ -823,6 +823,16 @@ const CommandDesc debug_cmd = {
|
||||||
for (auto& option : context.options().flatten_options())
|
for (auto& option : context.options().flatten_options())
|
||||||
write_debug(" * " + option->name() + ": " + option->get_as_string());
|
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
|
else
|
||||||
throw runtime_error("unknown debug command '" + parser[0] + "'");
|
throw runtime_error("unknown debug command '" + parser[0] + "'");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,17 @@
|
||||||
|
|
||||||
#include "containers.hh"
|
#include "containers.hh"
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
#include "vector.hh"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename Value>
|
template<typename Value, MemoryDomain domain = MemoryDomain::Undefined>
|
||||||
class IdMap
|
class IdMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using value_type = std::pair<String, Value>;
|
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 iterator = typename container_type::iterator;
|
||||||
using const_iterator = typename container_type::const_iterator;
|
using const_iterator = typename container_type::const_iterator;
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,11 @@ void StringRegistry::release(size_t slot) noexcept
|
||||||
if (--m_storage[slot].refcount == 0)
|
if (--m_storage[slot].refcount == 0)
|
||||||
{
|
{
|
||||||
m_free_slots.push_back(slot);
|
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()});
|
auto it = m_slot_map.find(StringView{data.data(), (int)data.size()});
|
||||||
kak_assert(it != m_slot_map.end());
|
kak_assert(it != m_slot_map.end());
|
||||||
m_slot_map.erase(it);
|
m_slot_map.erase(it);
|
||||||
data = std::vector<char>{};
|
data = Vector<char, MemoryDomain::InternedString>{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
#include "utils.hh"
|
#include "utils.hh"
|
||||||
#include "unordered_map.hh"
|
#include "unordered_map.hh"
|
||||||
|
#include "vector.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -20,9 +21,13 @@ private:
|
||||||
void release(size_t slot) noexcept;
|
void release(size_t slot) noexcept;
|
||||||
|
|
||||||
UnorderedMap<StringView, size_t> m_slot_map;
|
UnorderedMap<StringView, size_t> m_slot_map;
|
||||||
std::vector<size_t> m_free_slots;
|
Vector<size_t, MemoryDomain::InternedString> m_free_slots;
|
||||||
struct DataAndRefCount { std::vector<char> data; int refcount; };
|
struct DataAndRefCount
|
||||||
std::vector<DataAndRefCount> m_storage;
|
{
|
||||||
|
Vector<char, MemoryDomain::InternedString> data;
|
||||||
|
int refcount;
|
||||||
|
};
|
||||||
|
Vector<DataAndRefCount, MemoryDomain::InternedString> m_storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InternedString : public StringView
|
class InternedString : public StringView
|
||||||
|
|
72
src/memory.hh
Normal file
72
src/memory.hh
Normal 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
|
|
@ -2,14 +2,16 @@
|
||||||
#define unordered_map_hh_INCLUDED
|
#define unordered_map_hh_INCLUDED
|
||||||
|
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
|
#include "memory.hh"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename Key, typename Value>
|
template<typename Key, typename Value, MemoryDomain domain = MemoryDomain::Undefined>
|
||||||
using UnorderedMap = std::unordered_map<Key, Value, Hash<Key>>;
|
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
16
src/vector.hh
Normal 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
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
#include "buffer.hh"
|
#include "buffer.hh"
|
||||||
#include "interned_string.hh"
|
#include "interned_string.hh"
|
||||||
|
#include "unordered_map.hh"
|
||||||
|
#include "vector.hh"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
|
@ -44,9 +45,9 @@ public:
|
||||||
UsedLetters letters;
|
UsedLetters letters;
|
||||||
int refcount;
|
int refcount;
|
||||||
};
|
};
|
||||||
using WordToInfo = UnorderedMap<InternedString, WordInfo>;
|
using WordToInfo = UnorderedMap<InternedString, WordInfo, MemoryDomain::WordDB>;
|
||||||
private:
|
private:
|
||||||
using LineToWords = std::vector<WordList>;
|
using LineToWords = Vector<WordList, MemoryDomain::WordDB>;
|
||||||
|
|
||||||
void update_db();
|
void update_db();
|
||||||
void add_words(const WordList& words);
|
void add_words(const WordList& words);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user