Use a single allocation for SharedString::Storage

This commit is contained in:
Maxime Coste 2015-01-19 13:25:04 +00:00
parent 39689f0a18
commit 3697548e35
2 changed files with 22 additions and 10 deletions

View File

@ -35,7 +35,7 @@ void StringRegistry::debug_stats() const
for (auto& st : m_strings)
{
total_refcount += st.second->refcount - 1;
total_size += (int)st.second->content.size();
total_size += (int)st.second->length;
}
write_debug(" data size: " + to_string(total_size) + ", mean: " + to_string((float)total_size/count));
write_debug(" refcounts: " + to_string(total_refcount) + ", mean: " + to_string((float)total_refcount/count));

View File

@ -14,19 +14,31 @@ class SharedString : public StringView
public:
struct Storage : UseMemoryDomain<MemoryDomain::SharedString>
{
int refcount = 0;
Vector<char, MemoryDomain::SharedString> content;
int refcount;
int length;
char data[1];
Storage(StringView str)
StringView strview() const { return {data, length}; }
static Storage* create(StringView str)
{
content.reserve((int)str.length() + 1);
content.assign(str.begin(), str.end());
content.push_back('\0');
const int len = (int)str.length();
void* ptr = Storage::operator new(sizeof(Storage) + len);
Storage* res = reinterpret_cast<Storage*>(ptr);
memcpy(res->data, str.data(), len);
res->refcount = 0;
res->length = len;
res->data[len] = 0;
return res;
}
static void destroy(Storage* s)
{
Storage::operator delete(s, sizeof(Storage) + s->length);
}
StringView strview() const { return {&content.front(), &content.back()}; }
friend void inc_ref_count(Storage* s) { ++s->refcount; }
friend void dec_ref_count(Storage* s) { if (--s->refcount == 0) delete s; }
friend void dec_ref_count(Storage* s) { if (--s->refcount == 0) Storage::destroy(s); }
};
SharedString() = default;
@ -34,7 +46,7 @@ public:
{
if (not str.empty())
{
m_storage = new Storage{str};
m_storage = Storage::create(str);
StringView::operator=(m_storage->strview());
}
}