So I have been playing around with yaml-cpp as I want to use YAML for most of my game data files however I am running into some pretty big performance issues and not sure if it is something I am doing or the library itself.
I created this code in order to test a moderately sized file:
Player newPlayer = Player();
newPlayer.name = "new player";
newPlayer.maximumHealth = 1000;
newPlayer.currentHealth = 1;
Inventory newInventory;
newInventory.maximumWeight = 10.9f;
for (int z = 0; z < 10000; z++) {
InventoryItem* newItem = new InventoryItem();
newItem->name = "Stone";
newItem->baseValue = 1;
newItem->weight = 0.1f;
newInventory.items.push_back(newItem);
}
YAML::Node newSavedGame;
newSavedGame["player"] = newPlayer;
newSavedGame["inventory"] = newInventory;
This is where I ran into my first issue, memory consumption.
Before I added this code, the memory usage of my game was about 22MB. After I added everything expect the YAML::Node stuff, it went up to 23MB, so far nothing unexpected. Then when I added the YAML::Node and added data to it, the memory went up to 108MB. I am not sure why when I add the class instance it only adds like 1MB of memory but then copying that data to a YAML:Node instance, it take another 85MB of memory.
So putting that issue aside, I want want to test the performance of writing out the files. the initial attempt looked like this:
void YamlUtility::saveAsFile(YAML::Node node, std::string filePath) {
std::ofstream myfile;
myfile.open(filePath);
myfile << node << std::endl;
myfile.close();
}
To write out the file (that ends up to be about 570KB), it took about 8 seconds to do that. That seems really slow to me.
After read the documentation a little more I decide to try a different route using the YAML::Emitter, the implemntation looked like this:
static void buildYamlManually(std::ofstream& file, YAML::Node node) {
YAML::Emitter out;
out << YAML::BeginMap << YAML::Key << "player" << YAML::Value << YAML::BeginMap << YAML::Key << "name" << YAML::Value
<< node["player"]["name"].as<std::string>() << YAML::Key << "maximumHealth" << YAML::Value
<< node["player"]["maximumHealth"].as<int>() << YAML::Key << "currentHealth" << YAML::Value
<< node["player"]["currentHealth"].as<int>() << YAML::EndMap;
out << YAML::BeginSeq;
std::vector<InventoryItem*> items = node["inventory"]["items"].as<std::vector<InventoryItem*>>();
for (InventoryItem* const value : items) {
out << YAML::BeginMap << YAML::Key << "name" << YAML::Value << value->name << YAML::Key << "baseValue"
<< YAML::Value << value->baseValue << YAML::Key << "weight" << YAML::Value << value->weight << YAML::EndMap;
}
out << YAML::EndSeq;
out << YAML::EndMap;
file << out.c_str() << std::endl;
}
While this did seem to improve the speed, it was still take about 7 seconds instead of 8 seconds.
Since it has been a while since I used C++ and was not sure if this was normal, I decided to for testing just write a simple method to manually generate the YAMLin this use case, that looked something like this:
static void buildYamlManually(std::ofstream& file, SavedGame savedGame) {
file << "player: \n"
<< " name: " << savedGame.player.name << "\n maximumHealth: " << savedGame.player.maximumHealth
<< "\n currentHealth: " << savedGame.player.currentHealth << "\ninventory:"
<< "\n maximumWeight: " << savedGame.inventory.maximumWeight << "\n items:";
for (InventoryItem* const value : savedGame.inventory.items) {
file << "\n - name: " << value->name << "\n baseValue: " << value->baseValue
<< "\n weight: " << value->weight;
}
}
This wrote the same file and it took about 0.15 seconds which seemed a lot more to what I was expecting.
While I would expect some overhead in using yaml-cpp to manage and write out YAML files, it consuming 70X+ the amount of memory and it being 40X+ slower in writing files seems really bad.
I am not sure if I am doing something wrong with how I am using yaml-cpp that would be causing this issue or maybe it was never design to handle large files but was just wondering if anyone has any insight on what might be happening here (or an alternative to dealing with YAMLin C++)?