Microprofiler Labels Not Shown: $UserToken_##, $Script, $namecall, etc

User-definied MicroProfiler labels show up as $UserToken_XX. Scripts show up as $Script. Method usage shows up as $namecall. Whenever this bug happens, all labels in the frame disappear.

I would expect these to have the developer-given labels, not internal names.

I have no idea when this started, but it’s been around for a while.


This makes debugging performance issues very difficult: I can’t use the MicroProfiler to track down bugs. This is especially an issue in big places with lots of moving parts, which is where this bug occurs! I’m trying to solve some FPS problems in a place at the moment, but this is making things a lot more difficult.

image

It would be really useful to know what these mean


The following repro hides/shows labels every other second

Note that this bug does not require the profilebegin and profileend calls – it will still happen if you comment them out, because the bug is caused by the number of labels/bars created from calling IsA.

local function shortProfile(n, makeThousandsOfLabels)
	debug.profilebegin(n)  -- let's make it clear if we're hiding or showing.
	for _ = 1, 20 do
		local start = tick()
		if makeThousandsOfLabels then
			for i = 1, 2000 do
				workspace:IsA("Workspace")  -- makes thousands of `IsA` labels
			end
		end
		while tick() - start < 0.001 do  -- block thread for a while so we can see it in the profiler easily
			
		end
	end
	debug.profileend()
end


game:GetService("RunService").Stepped:connect(function()
	if math.floor(tick())%2 == 0 then  -- if integer of tick() is even then...
		shortProfile("frame-hidden", true)
	else  -- if integer of tick is odd then...
		shortProfile("frame-shown", false)
	end
	-- hides labels for 1 second, then shows for 1 second.
end)

9 Likes

For what it’s worth, I remember looking into this a while back (1-2 months ago?) and all I could figure out was that it doesn’t always happen.

A bit of an update: I made a plugin to work around this bug!

It puts in scripts to map the numbers to the labels. I’ve only tested it in Studio so far, and it has been accurate there.
Edit: looks like it’s 4 too high online.

If you want to see the source, run this in the command bar:

local objects = game:GetObjects("rbxassetid://1096416568") for _, v in next, objects do v.Parent = game.ServerStorage end game.Selection:Set(objects)

To use: Open the Plugins tab and click ‘Update’ on ‘Profile Determination’

Came up with a repro! It seems to be caused by there being too many labels such that the microprofiler can’t keep up. The following script will switch between hiding labels and showing labels every second:

local function shortProfile(n, makeThousandsOfLabels)
	debug.profilebegin(n)  -- let's make it clear if we're hiding or showing.
	for _ = 1, 20 do
		local start = tick()
		if makeThousandsOfLabels then
			for i = 1, 2000 do
				workspace:IsA("Workspace")  -- makes thousands of `IsA` labels
			end
		end
		while tick() - start < 0.001 do  -- block thread for a while so we can see it in the profiler easily
			
		end
	end
	debug.profileend()
end


game:GetService("RunService").Stepped:connect(function()
	if math.floor(tick())%2 == 0 then  -- if integer of tick() is even then...
		shortProfile("frame-hidden", true)
	else  -- if integer of tick is odd then...
		shortProfile("frame-shown", false)
	end
	-- hides labels for 1 second, then shows for 1 second.
end)

Perhaps not showing labels after a certain point is reasonable, but the current threshold is low enough to affect actual games.

1 Like

Profiler has a fixed size ring buffer for all label data. When looking at labels, prefer looking at later frames as opposed to earlier frames - since it’s a ring buffer, last frame will almost always have all the necessary data.

4 Likes

This bug made debugging our Rolantis event game for performance almost impossible, because even when using a single profilebegin/end call the label would already not be showing after some frames. It’s hard to correlate sections labeled with a random name back to the code that triggered that token, unless it is expected behavior that we toggle-comment these on/off constantly, which I doubt is the case. This “fixed size ring buffer” should definitely be increased or the mechanism for custom user labels should be changed, because this is not usable in a production game that has lots of systems in it right now.

2 Likes

I saw someone running into this issue earlier today and had to link this post. I’ve also ran into this issue while working with other developers on various projects multiple times since I posted this topic.

It seems like user token ids are assigned once per session in a first-come-first-serve basis. This means that at any given time while looking at a single microprofiler, each user token id matches a single label.

Is it possible the microprofiler could be improved so that user tokens don’t take up space on the ring buffer, and instead a dictionary of user token id -> label could be used? This would both free up space in the ring buffer for other things (such as script name labels) and make user tokens always show up.

This would be a great improvement for Roblox developers, especially given that Roblox games are becoming increasingly more complex so this microprofiler ring buffer limitation is being encountered increasingly often.

2 Likes