From 9b30e7469a5832166b244a85065b3e1efb30cc90 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 7 Jan 2015 19:29:31 +0000 Subject: [PATCH] Add initial memory domain allocation tracking support --- src/commands.cc | 12 ++++++- src/id_map.hh | 7 ++-- src/interned_string.cc | 4 +-- src/interned_string.hh | 11 +++++-- src/memory.hh | 72 ++++++++++++++++++++++++++++++++++++++++++ src/unordered_map.hh | 6 ++-- src/vector.hh | 16 ++++++++++ src/word_db.hh | 7 ++-- 8 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 src/memory.hh create mode 100644 src/vector.hh diff --git a/src/commands.cc b/src/commands.cc index de7c3281..3dced933 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -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::byte_count)); + write_debug("InternedString: " + to_string(UsedMemory::byte_count)); + write_debug("BufferContent: " + to_string(UsedMemory::byte_count)); + write_debug("BufferMeta: " + to_string(UsedMemory::byte_count)); + write_debug("WordDB: " + to_string(UsedMemory::byte_count)); + write_debug("Undefined: " + to_string(UsedMemory::byte_count)); + } else throw runtime_error("unknown debug command '" + parser[0] + "'"); } diff --git a/src/id_map.hh b/src/id_map.hh index 591ec629..4854e065 100644 --- a/src/id_map.hh +++ b/src/id_map.hh @@ -3,18 +3,17 @@ #include "containers.hh" #include "string.hh" - -#include +#include "vector.hh" namespace Kakoune { -template +template class IdMap { public: using value_type = std::pair; - using container_type = std::vector; + using container_type = Vector; using iterator = typename container_type::iterator; using const_iterator = typename container_type::const_iterator; diff --git a/src/interned_string.cc b/src/interned_string.cc index 5395cf02..3646e2f8 100644 --- a/src/interned_string.cc +++ b/src/interned_string.cc @@ -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& 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{}; + data = Vector{}; } } diff --git a/src/interned_string.hh b/src/interned_string.hh index b96bbfea..25c84a85 100644 --- a/src/interned_string.hh +++ b/src/interned_string.hh @@ -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 m_slot_map; - std::vector m_free_slots; - struct DataAndRefCount { std::vector data; int refcount; }; - std::vector m_storage; + Vector m_free_slots; + struct DataAndRefCount + { + Vector data; + int refcount; + }; + Vector m_storage; }; class InternedString : public StringView diff --git a/src/memory.hh b/src/memory.hh new file mode 100644 index 00000000..36b5c31c --- /dev/null +++ b/src/memory.hh @@ -0,0 +1,72 @@ +#ifndef memory_hh_INCLUDED +#define memory_hh_INCLUDED + +#include + +#include "assert.hh" + +namespace Kakoune +{ + +enum class MemoryDomain +{ + Undefined, + String, + InternedString, + BufferContent, + BufferMeta, + WordDB +}; + +template +struct UsedMemory +{ + static size_t byte_count; +}; + +template +size_t UsedMemory::byte_count = 0; + +template +struct Allocator +{ + using value_type = T; + + Allocator() = default; + template + Allocator(const Allocator&) {} + + template + struct rebind { using other = Allocator; }; + + T* allocate(size_t n) + { + size_t size = sizeof(T) * n; + UsedMemory::byte_count += size; + return reinterpret_cast(malloc(size)); + } + + void deallocate(T* ptr, size_t n) + { + size_t size = sizeof(T) * n; + kak_assert(UsedMemory::byte_count >= size); + UsedMemory::byte_count -= size; + free(ptr); + } +}; + +template +bool operator==(const Allocator& lhs, const Allocator& rhs) +{ + return d1 == d2; +} + +template +bool operator!=(const Allocator& lhs, const Allocator& rhs) +{ + return d1 != d2; +} + +} + +#endif // memory_hh_INCLUDED diff --git a/src/unordered_map.hh b/src/unordered_map.hh index a803186b..b114df69 100644 --- a/src/unordered_map.hh +++ b/src/unordered_map.hh @@ -2,14 +2,16 @@ #define unordered_map_hh_INCLUDED #include "hash.hh" +#include "memory.hh" #include namespace Kakoune { -template -using UnorderedMap = std::unordered_map>; +template +using UnorderedMap = std::unordered_map, std::equal_to, + Allocator, domain>>; } diff --git a/src/vector.hh b/src/vector.hh new file mode 100644 index 00000000..987b80f9 --- /dev/null +++ b/src/vector.hh @@ -0,0 +1,16 @@ +#ifndef vector_hh_INCLUDED +#define vector_hh_INCLUDED + +#include "memory.hh" + +#include + +namespace Kakoune +{ + +template +using Vector = std::vector>; + +} + +#endif // vector_hh_INCLUDED diff --git a/src/word_db.hh b/src/word_db.hh index ef45bfa5..50496113 100644 --- a/src/word_db.hh +++ b/src/word_db.hh @@ -3,8 +3,9 @@ #include "buffer.hh" #include "interned_string.hh" +#include "unordered_map.hh" +#include "vector.hh" -#include #include namespace Kakoune @@ -44,9 +45,9 @@ public: UsedLetters letters; int refcount; }; - using WordToInfo = UnorderedMap; + using WordToInfo = UnorderedMap; private: - using LineToWords = std::vector; + using LineToWords = Vector; void update_db(); void add_words(const WordList& words);