1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-15 11:46:56 +02:00

Implemented string deduplication for serializer

Every unique string will now be serialized only once.
Reduces save size by ~20%
This commit is contained in:
Ivan Savenko 2024-05-07 14:50:21 +00:00
parent 5b182c31df
commit 87eac164e6
4 changed files with 67 additions and 6 deletions

View File

@ -156,6 +156,7 @@ public:
bool reverseEndianness; //if source has different endianness than us, we reverse bytes bool reverseEndianness; //if source has different endianness than us, we reverse bytes
Version version; Version version;
std::vector<std::string> loadedStrings;
std::map<ui32, void*> loadedPointers; std::map<ui32, void*> loadedPointers;
std::map<const void*, std::shared_ptr<void>> loadedSharedPointers; std::map<const void*, std::shared_ptr<void>> loadedSharedPointers;
IGameCallback * cb = nullptr; IGameCallback * cb = nullptr;
@ -450,11 +451,35 @@ public:
} }
} }
void load(std::string &data) void load(std::string &data)
{
if (hasFeature(Version::COMPACT_STRING_SERIALIZATION))
{
int32_t length;
load(length);
if (length < 0)
{
int32_t stringID = -length - 1; // -1, -2 ... -> 0, 1 ...
data = loadedStrings[stringID];
}
if (length == 0)
{
data = {};
}
if (length > 0)
{
data.resize(length);
this->read(static_cast<void *>(data.data()), length, false);
loadedStrings.push_back(data);
}
}
else
{ {
ui32 length = readAndCheckLength(); ui32 length = readAndCheckLength();
data.resize(length); data.resize(length);
this->read(static_cast<void *>(data.data()), length, false); this->read(static_cast<void *>(data.data()), length, false);
} }
}
template<typename... TN> template<typename... TN>
void load(std::variant<TN...> & data) void load(std::variant<TN...> & data)

View File

@ -113,6 +113,7 @@ class DLL_LINKAGE BinarySerializer : public CSaverBase
public: public:
using Version = ESerializationVersion; using Version = ESerializationVersion;
std::map<std::string, uint32_t> savedStrings;
std::map<const void*, ui32> savedPointers; std::map<const void*, ui32> savedPointers;
const Version version = Version::CURRENT; const Version version = Version::CURRENT;
@ -322,11 +323,42 @@ public:
for(auto i = d.begin(); i != d.end(); i++) for(auto i = d.begin(); i != d.end(); i++)
save(*i); save(*i);
} }
void save(const std::string &data) void save(const std::string &data)
{
if (hasFeature(Version::COMPACT_STRING_SERIALIZATION))
{
if (data.empty())
{
save(ui32(0));
return;
}
auto it = savedStrings.find(data);
if (it == savedStrings.end())
{
save(ui32(data.length()));
this->write(static_cast<const void *>(data.data()), data.size());
// -1, -2...
int32_t newStringID = -1 - savedStrings.size();
savedStrings[data] = newStringID;
}
else
{
int32_t index = it->second;
save(index);
}
}
else
{ {
save(ui32(data.length())); save(ui32(data.length()));
this->write(static_cast<const void *>(data.data()), data.size()); this->write(static_cast<const void *>(data.data()), data.size());
} }
}
template <typename T1, typename T2> template <typename T1, typename T2>
void save(const std::pair<T1,T2> &data) void save(const std::pair<T1,T2> &data)
{ {

View File

@ -73,6 +73,7 @@ void CConnection::sendPack(const CPack * pack)
boost::mutex::scoped_lock lock(writeMutex); boost::mutex::scoped_lock lock(writeMutex);
auto connectionPtr = networkConnection.lock(); auto connectionPtr = networkConnection.lock();
serializer->savedStrings.clear();
if (!connectionPtr) if (!connectionPtr)
throw std::runtime_error("Attempt to send packet on a closed connection!"); throw std::runtime_error("Attempt to send packet on a closed connection!");
@ -91,6 +92,7 @@ CPack * CConnection::retrievePack(const std::vector<std::byte> & data)
packReader->buffer = &data; packReader->buffer = &data;
packReader->position = 0; packReader->position = 0;
deserializer->loadedStrings.clear();
*deserializer & result; *deserializer & result;

View File

@ -44,5 +44,7 @@ enum class ESerializationVersion : int32_t
RELEASE_150 = ARTIFACT_COSTUMES, // for convenience RELEASE_150 = ARTIFACT_COSTUMES, // for convenience
CURRENT = ARTIFACT_COSTUMES COMPACT_STRING_SERIALIZATION,
CURRENT = COMPACT_STRING_SERIALIZATION
}; };