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) for (auto& st : m_strings)
{ {
total_refcount += st.second->refcount - 1; 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(" 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)); 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: public:
struct Storage : UseMemoryDomain<MemoryDomain::SharedString> struct Storage : UseMemoryDomain<MemoryDomain::SharedString>
{ {
int refcount = 0; int refcount;
Vector<char, MemoryDomain::SharedString> content; 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); const int len = (int)str.length();
content.assign(str.begin(), str.end()); void* ptr = Storage::operator new(sizeof(Storage) + len);
content.push_back('\0'); 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 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; SharedString() = default;
@ -34,7 +46,7 @@ public:
{ {
if (not str.empty()) if (not str.empty())
{ {
m_storage = new Storage{str}; m_storage = Storage::create(str);
StringView::operator=(m_storage->strview()); StringView::operator=(m_storage->strview());
} }
} }