How efficient is accessing data tables?

I would like to know how efficient it is to:

  1. Search for a data
  2. Get data by row name

Is it O(1) or O(n) ? Do I have to manually cache Data Table in memory or will they be cached into memory at runtime?

Imagine I have to implement an item inventory system for an RPG.

Data Table Method:
I could save all basic data related to all items such as Name, Type, Value, Weight and Static Mesh Reference, in a Data Table. Then I can have a common class/object and assign these values from data table at runtime when needed. (there will be many Get Data Table Row calls). However, unique items need to have their own classes.

OOP Method:
Create basic item class and all items inherit from it as a separate class. Unique items are dealt the same way.

Which method above will be efficient in time ? and in space ?

I’m hoping that a map is like a C# dictionary which is very fast access, and that datatable access is as fast as that. But I don’t know and haven’t measured performance with a data table of significant size.

the performance should be great in-game, but the struct editor and datatable editor within unreal will lag horribly past around 100 or so rows. RAM is great for that kinda stuff at runtime, but I’d recommend writing the struct and enums or other stuff straight into source for ease of editing.

You can also pull datatables out of unreal and edit them with Gsheets/excel and then replace them just ensure you save as a .csv

Im making an extensive data driven Rpg thats drawn from my co-dev’s work of 20 years creating a Pen and paper game (which is actively played) I am using massive data driven tables for everything from item generation, player stats (temp, elevation,sickness, hunger, thirst) and have not noticed any decrease in performance pulling from the data sets (which is done though the use of onconstruct or event begin play (not on tick)

I have been smart about my data, I have sectioned it so instead of one giant table, its many smaller tables which direct the information where its needed and I don’t constantly pull or set data in tables (only at certain points, like skill changes) instead of tracking things like health which constantly update (this is handled though Var’s and then verified by the server for multiplayer (as a basic anti-cheat)

my world includes huge open area’s an infinite procedurally generated dungeon and 2&4k textures (with tessellation/displacement) and still no performance drop, data tables are absolutely the way to go, and its far easier to deal with finding/changing variables this way.

there is apparently a known issue when a DT gets too big in Unreal editor environment (over 500) but when launches in-game/standalone no issues with data slowdown.

2 Likes

Data Tables are the way to go for data driven design. You won’t run into any performance issues in 99.99% of the use-cases, I use them extensively for the use-case you’ve described.

@Demonsunder: Thank you. Do you spawn a loader object which calls the data table, then destroy the object when it’s done? Essentially, I’m trying to avoid having everything that’s in the data table stored in memory at all times (skeletal meshes for armor), and if I keep the call to the data table in the function on the player character, I’m worried they will be.

It only stores them as reference, you don’t have to worry about memory bloat.

Wrong, memory bloat from refs can be substantial. In fact, mine is, and I need a solution. My question still stands.

Personally I haven’t found a reasonable way to use BP Datatables. The answers in this Thread (just like many Inventory Systems in the Marketplace) are disturbing. So I’d like to second Nerdballer’s Question. Although I don’t see a Loader object solving this by any means.

Youre right. I’ve tested and loader objects do nothing.

If you’re doing it mainly for an inventory, you’re in luck: arpg example project has a nice solution for you. Just copy it. As the visuals of an inventory are client-side, it’s not a problem.

My problem is I need to roll in networking with my system. In other words, you haven’t loaded in on your client a reference for every armor in the game, so when another player becomes net relevant, it needs to do a check to see if it needs to load their armor. I’ll probably edit Replication Graph for this, but it’s a bear.

I think you’re both using it wrong. You should never store non-transient raw pointers to UObjects inside a datatable or inside any UObject derived class. If you do so the object that it’s pointing to will be loaded automatically with the object containing the pointer. You should use TSoftObjectPtr to reference objects and load them manually during runtime. This way the objects won’t be automatically loaded when the datatable is loaded.

3 Likes

The thing is this topic is about BP (Blueprint only) Data tables. At least I was talking about them. Which to my knowledge doesn’t allow the usage of SoftRefs, or do they?

1 Like

Soft refs ARE available in blueprints.

[In fact, Datatables documentation last paragraph][2] specifically adresses this problem: “In the above DataTable example, the asset that is referenced is a lazy loaded asset (TSoftObjectPtr handles this). If the Asset field type was set to UTexture, all of the assets would be loaded whenever the DataTable was loaded.”

Edit variables type and hover type name in the list and options will appear. Here’s a screenshot pulled from google, but it’s not super clear. A quick search “how to” shouldn’t be hard to find though.

227504-variable.png

2 Likes

Yep, this is the solution. Store all your struct and class refs in data tables as soft object refs or soft class refs, then async load them (there’s a blueprint node) to use them in game.

It’s important to use soft refs because everything that’s a hard ref is stored in memory, so a data table with hard refs will load every single hard ref in it every time it’s accessed, so that isn’t scalable for a mid-large game.

For those new to soft refs, using them will cause a crash if you try to do something with them before loading them, as they’re only a pointer to the class, not the actual class loaded into memory, so load them first, then off the async load finished pin, do the rest of your logic with them.

This is the best-practice way. The load times are inconsequential, and it keeps memory to a minimum. Can have a game with tens of thousands of unique items no problem.

3 Likes

Not really. It’s one solution.
Other possibilities would range from using an actual database to query the data to simply create an instanced mesh to blueprint replacement system.

There’s also the argument that maybe One needs all objects to be in memory when the data table is loaded. You can’t know for sure unless it’s your system and you are working on it, so it’s kind of pointless I suppose.

Then crash again…
Before you do ANYTHING even off the load finished pin, add an IsValid check :wink:

1 Like

Yeah that still lags with more data in the editor, you dont even need 100 rows, just add several FButtonStyles which each consume 768 bytes, and having 6-8 of them in one row, will lag when you switch between rows, otherwise its okay