ProfileService taking a long time to release a profile

Hello,

So currently in my game, I am having loading time issues, I’ve noticed that the first time that a player joins, the loading screen loads in 0 seconds meaning it gets the players data in 0 seconds, but when they leave and join again, it takes 20 seconds and stays like that until you leave and wait a long time. Is this due to ProfileService taking a long time to release the profile? I’ve been trying to look into this for the past 3-4 days and I haven’t really found a lot. So I am just wondering how long it takes ProfileService to release a profile and if there is any way to make it faster.

This is my code to load and release a profile

local function PlayerAdded(player : Player)
	ProfileStore:LoadProfileAsync(player, true):After(function(success, playerProfile)
		if not success then
			player:Kick(DataErrorMessage)
			return
		end
		
		--/ Create leaderstats
		playerProfile:CreateProfileLeaderstats(player, {"KOs", "Cash"})
		
		local profile = playerProfile.Profile

		local dummy = {
			Data = {}
		}
		local callbacks = {}

		--/ Value Changing
		dummy.Data.__index = function(_,index)
			return profile.Data[index]
		end
		dummy.__index = function(_,index)
			if (index ~= "Data") then
				return profile[index]
			end
		end

		dummy.Data.__newindex = function(_,index,value)
			profile.Data[index] = value

			local callback = callbacks[index]
			if not callback or typeof(callback) ~= "table" then return end

			for _, callback in callback do
				coroutine.wrap(callback)(value)
			end
		end
		dummy.__newindex = function(_,index,value)
			profile[index] = value
		end

		setmetatable(dummy.Data,dummy.Data)
		setmetatable(dummy,dummy)

		function dummy:OnDataValueChanged(index, callback)
			if (not callbacks[index]) then
				callbacks[index] = {}
			end
			table.insert(callbacks[index],callback)

			local Connection = {}
			function Connection:Disconnect()
				table.remove(callbacks[index],table.find(callbacks[index],callback))
			end
			return Connection
		end
		
		
		--/ Global Keys
		for _, globalKey in playerProfile:GetGlobalKeys() do
			coroutine.wrap(HandleGlobalKey)(globalKey, profile)
		end
		playerProfile.GlobalKeyAdded:Connect(function(globalKey)
			HandleGlobalKey(globalKey, profile)
		end)
		
		
		PSManager.Profiles[player] = dummy
	end)
end
for _, player in srv.players:GetPlayers() do
	coroutine.wrap(PlayerAdded)(player)
end
srv.players.PlayerAdded:Connect(PlayerAdded)

srv.players.PlayerRemoving:Connect(function(player : Player)
	PSManager.Profiles[player] = nil
	ProfileStore:UnclaimSessionLock(player)
end)

I am using EasyProfile for my ProfileService manager.

Any help will be appreciated!

1 Like

I recommend looking at the documentation more closely

1 Like

I’ve already looked at it multiple times, what should I look at? There’s not really much in the documentation.

1 Like

Take a look at this

You also shouldn’t be manually removing the profile from the list.

Very helpful, yes I fixed my issue immediately when you recommend to check the documentation.

I am only manually removing the profile from my own module not EasyProfile. This is my whole script

local DataErrorMessage = "Could not load data, try again shortly. If issue persists, open a ticket!"
local LoadType = "ForceLoad"


local gameProperties, srv = _G.GameProperties, _G.GameServices


local profileService = require(script:WaitForChild("EasyProfile"))
local playerTemplate = require(script:WaitForChild("PlayerTemplate"))

local DataKey = gameProperties.DataKey
local ProfileStore = profileService.CreateProfileStore(
	DataKey,
	playerTemplate,
	"<default_key>-<userid>"
)



local PSManager = {
	Profiles = {}
}


local function HandleGlobalKey(globalKey, profile) --> Value, Key, KeyId
	local value, key, keyId = globalKey.Value, globalKey.Key, globalKey.KeyId
	if not keyId then
		return
	end

	if key == "Warning" then
		if value == "reset" then
			profile.Data.Warnings = {}
		elseif typeof(value) == "table" then
			table.insert(profile.Data.Warnings, {
				admin = value.admin,
				reason = value.reason,
				warnedAt = value.sendTime
			})
		end
	end
end

local function PlayerAdded(player : Player)
	ProfileStore:LoadProfileAsync(player, true, LoadType):After(function(success, playerProfile, ...)
		if not success then
			player:Kick(DataErrorMessage)
			return
		end
		
		local metaData = playerProfile:GetMetaData()
		if metaData.ProfileActiveSession.jobId ~= game.JobId then
			player:Kick("Profile is already loaded in another server, please wait before rejoining! If this continues, open a ticket!")
			return
		end
		
		--/ Create leaderstats
		playerProfile:CreateProfileLeaderstats(player, {"KOs", "Cash"})
		
		local profile = playerProfile.Profile

		local dummy = {
			Data = {}
		}
		local callbacks = {}

		--/ Value Changing
		dummy.Data.__index = function(_,index)
			return profile.Data[index]
		end
		dummy.__index = function(_,index)
			if (index ~= "Data") then
				return profile[index]
			end
		end

		dummy.Data.__newindex = function(_,index,value)
			profile.Data[index] = value

			local callback = callbacks[index]
			if not callback or typeof(callback) ~= "table" then return end

			for _, callback in callback do
				coroutine.wrap(callback)(value)
			end
		end
		dummy.__newindex = function(_,index,value)
			profile[index] = value
		end

		setmetatable(dummy.Data,dummy.Data)
		setmetatable(dummy,dummy)

		function dummy:OnDataValueChanged(index, callback)
			if (not callbacks[index]) then
				callbacks[index] = {}
			end
			table.insert(callbacks[index],callback)

			local Connection = {}
			function Connection:Disconnect()
				table.remove(callbacks[index],table.find(callbacks[index],callback))
			end
			return Connection
		end
		
		
		--/ Global Keys
		for _, globalKey in playerProfile:GetGlobalKeys() do
			coroutine.wrap(HandleGlobalKey)(globalKey, profile)
		end
		playerProfile.GlobalKeyAdded:Connect(function(globalKey)
			HandleGlobalKey(globalKey, profile)
		end)
		
		
		PSManager.Profiles[player] = dummy
	end)
end
for _, player in srv.players:GetPlayers() do
	coroutine.wrap(PlayerAdded)(player)
end
srv.players.PlayerAdded:Connect(PlayerAdded)

srv.players.PlayerRemoving:Connect(function(player : Player)
	if PSManager.Profiles[player] ~= nil then
		PSManager.Profiles[player] = nil
		ProfileStore:UnclaimSessionLock(player, nil)
	end
end)




function PSManager:WaitForPlayerLoaded(player : Player) : Profile
	local profile = self.Profiles[player] if profile then return profile end
	repeat task.wait() profile = self.Profiles[player] until profile return profile
end

function PSManager:FetchProfile(...) : Profile
	return self:WaitForPlayerLoaded(...)
end

function PSManager:GetProfileStore()
	return ProfileStore
end

function PSManager:GetPlayerTemplate()
	return playerTemplate
end

return PSManager

You shouldn’t be talking if you have no idea what the code even does. It’s wrong which is why I’m suggesting taking a reread?

So to be clear, it’s just taking a while to load for the player? If so, please share some benchmarks.

I’m not sure if you think if it’s a EasyProfile issue but I don’t think it is, I think it’s just a ProfileService issue. If you look at my previous posts, I’ve reported the same thing but no help.

But here are some images posted by the community, they all seem to be the same through out. This ofcourse does not apply to Roblox Studio, not sure why.

First join after a while:
image

After:

You can see a major increase in loading time, from 0 seconds to over 24 seconds.

I’ve reread it and I don’t see anything wrong, if you can, please let me know what I wrote that is wrong.

same issue, diff profile manager
and you tell someone to “read docs”

thats not helpful
even my friend has this same issue which is why im on this thread in the first place

He’s mainly talking to me as he is the one who made EasyProfile so he’s assisting me. I don’t think he was trying to be rude or anything like that.

Well then it’s an issue with ps, there was no reason to be rude as that wasn’t my first suspicion