Slastraf Posted September 1 Posted September 1 Hi, when I create a reasonable amount of decals (~500), the process memory shoots through the roof. The ram usage exceeds 40 GB, this makes windows offload some ram onto the SSD, increasing map loading time by a lot. In this screenshot, I have only instantiated about 500 decals (total of 1000 nodes , of which every second is a decal). I would like to make this a somewhat production ready system even in the early stage, but I haven't handled many instantiated entities within leadwerks in the past. This is how I instantiate the decals: auto road = road_decal->Instantiate(world, false, false); //road->SetScale(1, 1, 1); road->SetRotation(0.0f, yawDegrees, 0.0f); road->SetPosition( midpoint.x, terrainY + 0.02f, midpoint.z ); road->SetScale(length*3, roadHeight, roadWidth); road->SetMaterial(road_material); road->SetNavObstacle(false); roadEntities.push_back(road); and somewhere before that : ... road_material = LoadMaterial("Materials/road_decal.mat"); road_decal = ::Leadwerks::CreateDecal( world )->As<Entity>(); ... The navmesh is built before the instantiation of the roads. TLDR; Instantiating many decals takes up a lot of RAM, and I think it is not supposed to be like that, and I think I am doing something wrong and need help. Quote
Slastraf Posted September 1 Author Posted September 1 std::vector<shared_ptr<Entity>> roadEntities; ... // Setup once auto road_material = LoadMaterial("Materials/road_decal.mat"); auto road_decal = ::Leadwerks::CreateDecal(Game::world)->As<Entity>(); road_decal->SetMaterial(road_material); //roadEntities.reserve(500); // Instantiate 500 decals for (int i = 0; i < 500; ++i) { // Replace these with your actual per-decal values float yawDegrees = 0.0f; // or compute per iteration Vec3 midpoint = { float(i)*2, 0.0f, 0.0f }; // or compute per iteration float terrainY = 0; // or compute per iteration float length = 100; // or compute per iteration float roadHeight = 10; // or compute per iteration float roadWidth = 100.0f; // or compute per iteration auto road = road_decal->Instantiate(Game::world, false, false); road->SetRotation(0.0f, yawDegrees, 0.0f); road->SetPosition(midpoint.x, terrainY + 0.02f, midpoint.z); road->SetScale(length * 3, roadHeight, roadWidth); road->SetMaterial(road_material); road->SetNavObstacle(false); roadEntities.push_back(road); Print("ok"); } Update, I couldnt replicate it with this, it showed that 500 decals seem to work very well actually Quote
Slastraf Posted September 2 Author Posted September 2 15 hours ago, Slastraf said: std::vector<shared_ptr<Entity>> roadEntities; ... // Setup once auto road_material = LoadMaterial("Materials/road_decal.mat"); auto road_decal = ::Leadwerks::CreateDecal(Game::world)->As<Entity>(); road_decal->SetMaterial(road_material); //roadEntities.reserve(500); // Instantiate 500 decals for (int i = 0; i < 500; ++i) { // Replace these with your actual per-decal values float yawDegrees = 0.0f; // or compute per iteration Vec3 midpoint = { float(i)*2, 0.0f, 0.0f }; // or compute per iteration float terrainY = 0; // or compute per iteration float length = 100; // or compute per iteration float roadHeight = 10; // or compute per iteration float roadWidth = 100.0f; // or compute per iteration auto road = road_decal->Instantiate(Game::world, false, false); road->SetRotation(0.0f, yawDegrees, 0.0f); road->SetPosition(midpoint.x, terrainY + 0.02f, midpoint.z); road->SetScale(length * 3, roadHeight, roadWidth); road->SetMaterial(road_material); road->SetNavObstacle(false); roadEntities.push_back(road); Print("ok"); } Update, I couldnt replicate it with this, it showed that 500 decals seem to work very well actually Another update, the code quoted here is sufficient to reproduce the issue. Using this code generating number of decals vs Ram usage : 100 | 9.6 GB 200,| 17,8 GB 300 | 26,1 GB To recap; I would like to build a road system where roads are made up of segments of decals, and I need lots of decals for that. The ram issue persists even if the decals have no material. Here is an updated code to test yourself: std::vector<shared_ptr<Entity>> roadEntities; ... auto road_decal = ::Leadwerks::CreateDecal(Game::world)->As<Entity>(); //road_decal->SetMaterial(road_material); //roadEntities.reserve(500); // Instantiate 500 decals for (int i = 0; i < 300; ++i) { // Replace these with your actual per-decal values float yawDegrees = 0.0f; // or compute per iteration Vec3 midpoint = { float(i)*2, 0.0f, 0.0f }; // or compute per iteration float terrainY = 0; // or compute per iteration float length = 100; // or compute per iteration float roadHeight = 10; // or compute per iteration float roadWidth = 100.0f; // or compute per iteration auto road = road_decal->Instantiate(Game::world, false, false); road->SetRotation(0.0f, yawDegrees, 0.0f); road->SetPosition(midpoint.x, terrainY + 0.02f, midpoint.z); road->SetScale(length * 3, roadHeight, roadWidth); //road->SetMaterial(road_material); road->SetNavObstacle(false); roadEntities.push_back(road); } Quote
Slastraf Posted September 3 Author Posted September 3 I have an update on the ram issue, The issue is fixed in the test code by prior reserving elements in the vector. std::vector<shared_ptr<Decal>> roadEntities; roadEntities.reserve(301); // and code as from my previous answer Here is what AI has to say about it: Quote Without reserve, your std::vector grows by repeated reallocations as you push_back 501 elements, each time allocating a larger array and moving all existing shared_ptrs, which can cause many short-lived allocations and deallocations that look like “RAM exploding” in profilers or during rapid growth. With reserve(501), the vector allocates enough space once up front, so all 501 push_backs just construct the shared_ptrs in place without further reallocations, eliminating the allocation churn. However, at my actual code , reserving the exact size of elements needed has so far NOT fixed the issue. The only difference in the code is that the roadEntities vector is a member of a class inheriting a component. Here is the screenshot for proof. I will provide my code afterwards: Here is the code #pragma once #include "Leadwerks.h" #include "..\BaseComponent.h" /... using namespace Leadwerks; // ---------------------- // Component // ---------------------- class LeadwerksRoads : public Component { //... private: void RenderRoads(); protected: std::vector<shared_ptr<Decal>> roadEntities; }; and void LeadwerksRoads::RenderRoads() { auto world = GetEntity()->GetWorld(); if (!world) return; int renderedCount = 0; int zeroLengthCount = 0; int decals = 0; roadEntities.clear(); roadEntities.reserve(roadGraph.edges.size()); Print("Reserved capacity: " + std::to_string(roadEntities.capacity())); for (const auto& edge : roadGraph.edges) { const float yawDegrees =0; ++renderedCount; float terrainY = 0; auto road = ::Leadwerks::CreateDecal(world); road->SetRotation(0.0f, yawDegrees, 0.0f); road->SetPosition( midpoint.x, terrainY + 0.02f, midpoint.z ); road->SetScale(length*3, roadHeight, roadWidth); road->SetMaterial(road_material); //road->SetNavObstacle(false); roadEntities.push_back(road); decals++; } Print( "Rendered " + std::to_string(decals) ); } The issue persists. I have not a clue what the compiler does. When printing "Reserved capacity" , the vector has the exact capacity as expected before the loop. I have cut some code but this is the one I use and still causes a ram buildup, even when reserving the elements. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.