Ridiculous module loading times

I have a module loader that loops through a folder of modules to basically load up my game. However, I’ve noticed that sometimes it returns loading times of like 5000ms(5 seconds) which is just insane.

My modules look something like this:

local Player = Players.LocalPlayer
local leaderstats = Player:WaitForChild("leaderstats")

local Gui = Player.PlayerGui:WaitForChild("MainGui")
local Module = {}

function Module:Init()

end

return Module

My modules are located in StarterPlayerScripts.
My module loader looks like this:

local Services = RunService:IsServer() and
	ServerScriptService.Server.Server.Services
local Controllers = RunService:IsClient() and
	Players.LocalPlayer.PlayerScripts.Client.Client.Controllers

local ModuleLoader = {}

function ModuleLoader:LoadDirectory(directory: Folder)
	for _, module: ModuleScript in (directory:GetChildren()) do
		if (not module:IsA("ModuleScript")) then
			warn("[ModuleLoader] - Found a non module inside of", directory)
			continue
		end

		task.spawn(function()
			local startTime = os.clock()
			local moduleInfo = require(module)
			
			print(string.format("[%.2f] %s", (os.clock() - startTime) * 1000, module.Name))
			if (moduleInfo.Init) then
				moduleInfo:Init()
			end
		end)
	end
end

Any help is appreciated, thanks.

Most likely caused by you yielding when requiring modules. For things like UI, I tend to throw them into ReplicatedStorage so I can initialize them right away. Sounds like a hassle to do but, when you incorporate a UI module, it is rather easy to work with…

Yeah this solution brought my loading times down significantly. Another question I have though, lets say you need a folder such as leaderstats which is created on runtime. Would you still define this variable at the top of your module?

It’s safe to assume that the leaderstats haven’t replicated to the client. Depending on your use case, which I’m assuming is potentially tying leaderstats into UI elements, you’ll want to avoid using WaitForChild at the top of your script. What I normally tend to do is a Promise based approach of PromiseChild or PromiseDescendant however, I’m going to assume you don’t work w/ Promises. Luckily you have an Init method for your service/controller setup so what you can do is something like:

-- in ur Init
local leaderstats = Player:FindFirstChild("Leaderstats")

Module._leaderstats = leaderstats -- keeps the global aspect of ur leaderstats self contained in ur module's table now...

if not Module._leaderstats then
    Player.ChildAdded:Connect(function(child: Instance)
        if child.Name ~= "leaderstats" then return end

        Module._leaderstats = child
    end)
end

If you can fill me in on what you’re needing these leaderstats for, I can probably help you come up w/ a better way to go about this.

Yeah I’m just using the leaderstats to set and update UI. I was thinking of instead of having the leaderstats variable defined at the top of the module, I just define it in the function that utilises the leaderstats. So for example the Init function calls a :SetMoneyUI and I define the leaderstats variable in the respective function.

Unless there is a better way to go about doing this?

I personally don’t rely on leaderstats and have separate forms of replication in place for data. It’s going to come down to how you do UI tbh. I would just go w/ the easiest solution you can come up with ngl.

1 Like

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