Performance between ways of defining table entries

Is there any kind of performance impact that matters between doing this:

table_ = {}

table_.x = 5

or this:

table_ = {
   x = 5
}
2 Likes

To answer your question, both of these operations take about the same amount of resources.
But if I may ask, what are you trying to do?

1 Like

Well, nothing special. I know and can work with the rules of both ways of doing it, just had a thought and wanted to know about performance.

1 Like

While I’m not entirely sure if this is how Roblox’s luau interpreter works, I do know in other languages that defining a table length like you did in the second option is more performant because defining a length tells the interpreter exactly how much memory to reserve for the table, as opposed to having to dynamically check memory each and every time the table is appended.

2 Likes

@ellienonekomimi thinking is entirely correct, and applies to most raw implementations of programming languages, including Lua 5.2.

Lua 5.2 (for better understanding)

Lua tables have 1. array part (storing indices 1...n, n € N) and 2. hash part (storing all other entries in a hash array through a hashing algorithm).

Array and hash part sizes are calculated to the power of 2, and rehashing is done each time the current part is too small to accomodate all entries (recalculating both array and hash part). Initial overhead is amortized in bigger tables, because the larger the table is, the fewer rehashings have to be performed (2^1 = 2; 2^2 = 4; 2^3 = 8, 2^4 = 16 …). One large table uses fewer resources than multiple small tables with the same exact elements.

Table constructed with table literals is always the most performant, and the hash part size remains zero in the case below.

local NolanMovies = {"Oppenheimer", "Interstellar"}

→ array part size: 2; hash part size: 0

table.insert(NolanMovies, "The Dark Knight") -- new element

→ rehashing; array part size: 4; hash part size: 0

Similarly, table space is preallocated if we define dictionaries in the following way:

local NolanMovies = {["Oppenheimer"] = 2023; ["Interstellar"] = 2014;}

→ array part size: 0; hash part size: 2

NolanMovies["The Dark Knight"] = 2008

→ rehashing; array part size: 0, hash part size: 4

Even if one of those movies above was set to nil, table size would remain stable until a new element was added and hashing was again required, which recalculates the sizes.

However, when a table is defined like this:

local NolanMovies = {[1] = "Oppenheimer", [2] = "Interstellar", [3] = "The Dark Knight"}

… vanilla Lua doesn’t recognize literals and treats the array as a “dictionary”, activating the hashing part, which spends a bit more memory and CPU time than arrays do.

In order to not make this post overly long, I’ll say that reserving space in modern Lua versions has a similar benefit to the advantages in Luau.

Luau

Luau is extremely well optimized, and improves the above logic a lot. I took the screenshots from the Performance site (link: Performance - Luau).

  1. Literals

Performance of table literals

  1. Preallocated space

Preallocated space

  1. Nevertheless (an important improvement compared to Lua)

Compiler optimizations on empty tables

  1. Appending to the table
  • Unknown table size? table.insert() is the fastest.
  • Known table size and known indices? t[i] combined with table.create(n) is the quickest.
5 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.