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({
|
||||
[](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] + "'");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>{};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
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
|
||||
|
||||
#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
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 "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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user