Efficient way of requiring modules in terms of performance

Hello,

I have seen different methods people use to require modules, so I had questions on which one would be more efficient and less costly to the performance of the game.

One way is your default way of requiring a module, which is defining it on top of your script to access it.

local replicatedStorage = game:GetService("ReplicatedStorage")
local module1 = require(game.ReplicatedStorage.Module1)
local module2 = require(game.ReplicatedStorage.Module2)
local module3 = require(game.ReplicatedStorage.Module3)
-- and so on.

However, if your experience has several scripts that needs these modules to operate, you would need to define it in every script. Thus, I have seen people define their modules under a _G variable which you can access in every script (depending Client or Server of course)

local replicatedStorage = game:GetService("ReplicatedStorage")
--//Defining a table to store my modules there
local tbl  = {}
local g = replicatedStorage:GetChildren()
for i = 1, #g do
    if g[i].ClassName == "ModuleScript" then
        --//Storing modules in dictionary
		tbl[g[i].Name] = require(g[i])
	end
end

--//Storing dictionary to _G variable
_G.module = tbl

As you can see I can access to my modules just using _G.module["ModuleName"] in any script depending if I defined it in a Server or LocalScript

So back to my question, which method would be more efficient and less costly to require a module. Does it matter how many modules you are storing in _G.module? Is it good practice to store all modules in _G.module?

Looking forward to your replies.

8 Likes

i believe it is best to load them normally, _g is a global module that is accessible in every script, this might impact the performance if it has to load the functions in every script in your game.

i’m not sure if _g gets loaded in all scripts if it’s not directly accessed by your script.

5 Likes

it is to be said that i personally do store modules in _g once in a while, as some modules might cause unwanted behaviour if loaded twice or more.

5 Likes

is there any way to see if the performance cost is significant? I rather access my modules using the _G method as it saves me the time to require it in the script.

5 Likes

Here’s my way of doing it, where I have used it in my DataPredict software library.

In a module script, you can do this:


module = {}

module.modulePart1 = require(modulePart1)
module.modulePart2 = require(modulePart2)
module.modulePart3 = require(modulePart3)

return module

So when you call if from another script it looks like this:


local module = require(module)

module.modulePart1:someFunction()
module.modulePart2:someFunction()
module.modulePart3:someFunction()

It saves you the access time from trying to find the addresses for individual modules.

6 Likes

Isn’t this the same method to the _G method above?

5 Likes

Not quite exactly. In my way, the module script parts would be under the main module script, so if you move around the main script, you only call require once, regardless the location of the main script.

Also, you set the module scripts to the _G.module, so there’s might a chance that hackers can change it since it is global for everyone if I am not mistaken.

Here’s the part where someone say that the hackers can access _G

5 Likes

testing shows that it does not impact performance.
https://streamable.com/kpgd9b

4 Likes

What if when you have like 60 modules under _G.module ?

5 Likes

I believe if you define _G.module in the client, only client can access this table. Exploiters can also access any modules by just requiring them

5 Likes

What happens if it was server side then? You might then going to have issues. At least for my require(), you can hide the module scripts in something like ServerScriptService, away from client access.

5 Likes

You really shouldn’t care about script startup performance. Requiring 100 module scripts is probably about 1 ms anyway (in comparison, a game running 60 fps has a delay of 16 ms per frame. Keep in mind requires are cached. Just don’t require a script every frame or something like that.

4 Likes

i meant to test this, but i had to go at the time.

1 Like

What about in terms of memory usage? Loading all these modules when sometimes you do not need them can take up space, no?

Modules are all cached. Every require to a module references the exact same table/function:/whatever

The default way is the most efficient way. Module scripts run once and return the exact same value for subsequent require’s.

1 Like

If its true what you say, isnt better to store them in a global variable to easily access them without requiring the module on top of your script

Exploiters can’t change _G for other people or for the server, since it isn’t replicated, it’s “local”. Remember, if it has nothing to do with physics (i.e. how parts move around like player characters), exploiters can only see changes to it on their machine! It is a simplification, though a vast majority of the time it holds true. Just wanted to clarify :slight_smile:

It is still bad. Even if they can’t make changes, they can at least read the codes and use them as a hint on how to exploit things.

It will just replicate on their screen, and also if you require these modules and delete them off of the client, they can not really read them